Skip to content

Commit 42a2949

Browse files
bryamzxzgregkh
authored andcommitted
selinux: require a class's permission values to cover its permission count
[ Upstream commit b98a8ac ] security_get_permissions() sizes an array by the class's permissions.nprim and fills it at value - 1, from the inherited common's permission table and then the class's own. A value no permission defines leaves a NULL that sel_make_perm_files() passes to d_alloc_name(), an oops inside sel_write_load() that strands selinux_state.policy_mutex and leaves every later load in uninterruptible sleep; two permissions sharing a value overwrite the first kstrdup(). Bounding each value by nprim catches neither, and neither would a count: the symbol table is keyed on the permission name, so duplicates pass. Track the values each permission table claims and require them to cover exactly what its count declares, rejecting a count no value can reach. Conforming policies are unaffected. Cc: stable@vger.kernel.org Fixes: 55fcf09 ("selinux: add support for querying object classes and permissions from the running policy") Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com> Signed-off-by: Paul Moore <paul@paul-moore.com> (cherry picked from commit b98a8ac) Signed-off-by: Wentao Guan <guanwentao@uniontech.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 6c2ab7c commit 42a2949

1 file changed

Lines changed: 46 additions & 5 deletions

File tree

security/selinux/ss/policydb.c

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,7 +1127,18 @@ int str_read(char **strp, gfp_t flags, struct policy_file *fp, u32 len)
11271127
return 0;
11281128
}
11291129

1130-
static int perm_read(struct policydb *p, struct symtab *s, struct policy_file *fp)
1130+
/*
1131+
* Bitmap of the permission values a symtab has claimed. Values are 1-based
1132+
* and bounded by SEL_VEC_MAX, the width of an access vector, so the whole set
1133+
* fits in a u32 and the callers reject an nprim past that width.
1134+
*/
1135+
static u32 perm_claimed_mask(u32 nprim)
1136+
{
1137+
return nprim ? U32_MAX >> (SEL_VEC_MAX - nprim) : 0;
1138+
}
1139+
1140+
static int perm_read(struct policydb *p, struct symtab *s,
1141+
struct policy_file *fp, u32 *claimed)
11311142
{
11321143
char *key = NULL;
11331144
struct perm_datum *perdatum;
@@ -1151,6 +1162,10 @@ static int perm_read(struct policydb *p, struct symtab *s, struct policy_file *f
11511162
/* indexes an nprim-sized array in security_get_permissions() */
11521163
if (perdatum->value > s->nprim)
11531164
goto bad;
1165+
/* two permissions cannot share one slot of that array */
1166+
if (*claimed & (1U << (perdatum->value - 1)))
1167+
goto bad;
1168+
*claimed |= 1U << (perdatum->value - 1);
11541169

11551170
rc = str_read(&key, GFP_KERNEL, fp, len);
11561171
if (rc)
@@ -1171,7 +1186,7 @@ static int common_read(struct policydb *p, struct symtab *s, struct policy_file
11711186
char *key = NULL;
11721187
struct common_datum *comdatum;
11731188
__le32 buf[4];
1174-
u32 i, len, nel;
1189+
u32 i, len, nel, claimed = 0;
11751190
int rc;
11761191

11771192
comdatum = kzalloc(sizeof(*comdatum), GFP_KERNEL);
@@ -1193,17 +1208,28 @@ static int common_read(struct policydb *p, struct symtab *s, struct policy_file
11931208
if (rc)
11941209
goto bad;
11951210
comdatum->permissions.nprim = le32_to_cpu(buf[2]);
1211+
/* no permission value can reach a slot past SEL_VEC_MAX */
1212+
rc = -EINVAL;
1213+
if (comdatum->permissions.nprim > SEL_VEC_MAX)
1214+
goto bad;
11961215

11971216
rc = str_read(&key, GFP_KERNEL, fp, len);
11981217
if (rc)
11991218
goto bad;
12001219

12011220
for (i = 0; i < nel; i++) {
1202-
rc = perm_read(p, &comdatum->permissions, fp);
1221+
rc = perm_read(p, &comdatum->permissions, fp, &claimed);
12031222
if (rc)
12041223
goto bad;
12051224
}
12061225

1226+
rc = -EINVAL;
1227+
if (claimed != perm_claimed_mask(comdatum->permissions.nprim)) {
1228+
pr_err("SELinux: common %s does not define every permission it declares\n",
1229+
key);
1230+
goto bad;
1231+
}
1232+
12071233
hash_eval(&comdatum->permissions.table, "common_permissions", key);
12081234

12091235
rc = symtab_insert(s, key, comdatum);
@@ -1339,7 +1365,7 @@ static int class_read(struct policydb *p, struct symtab *s, struct policy_file *
13391365
char *key = NULL;
13401366
struct class_datum *cladatum;
13411367
__le32 buf[6];
1342-
u32 i, len, len2, ncons, nel, val;
1368+
u32 i, len, len2, ncons, nel, val, claimed = 0, inherited = 0;
13431369
int rc;
13441370

13451371
cladatum = kzalloc(sizeof(*cladatum), GFP_KERNEL);
@@ -1367,6 +1393,10 @@ static int class_read(struct policydb *p, struct symtab *s, struct policy_file *
13671393
if (rc)
13681394
goto bad;
13691395
cladatum->permissions.nprim = le32_to_cpu(buf[3]);
1396+
/* no permission value can reach a slot past SEL_VEC_MAX */
1397+
rc = -EINVAL;
1398+
if (cladatum->permissions.nprim > SEL_VEC_MAX)
1399+
goto bad;
13701400

13711401
ncons = le32_to_cpu(buf[5]);
13721402

@@ -1401,11 +1431,22 @@ static int class_read(struct policydb *p, struct symtab *s, struct policy_file *
14011431
}
14021432
}
14031433
for (i = 0; i < nel; i++) {
1404-
rc = perm_read(p, &cladatum->permissions, fp);
1434+
rc = perm_read(p, &cladatum->permissions, fp, &claimed);
14051435
if (rc)
14061436
goto bad;
14071437
}
14081438

1439+
/* the class's own permissions must claim the slots the common leaves */
1440+
if (cladatum->comdatum)
1441+
inherited = cladatum->comdatum->permissions.nprim;
1442+
rc = -EINVAL;
1443+
if (claimed != (perm_claimed_mask(cladatum->permissions.nprim) &
1444+
~perm_claimed_mask(inherited))) {
1445+
pr_err("SELinux: class %s does not define every permission it declares\n",
1446+
key);
1447+
goto bad;
1448+
}
1449+
14091450
hash_eval(&cladatum->permissions.table, "class_permissions", key);
14101451

14111452
rc = read_cons_helper(p, &cladatum->constraints, ncons, 0, fp);

0 commit comments

Comments
 (0)