summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Göttsche <cgzones@googlemail.com>2026-09-03 13:35:38 +0200
committerPaul Moore <paul@paul-moore.com>2026-09-24 17:30:18 -0400
commit641bd5750517d2e5c128c566669c190857260693 (patch)
tree13403804cf533b16e3f0c4147f5a813a0bb5f6f1
parent508d1fcc2d099e1e8d9b6fc14cb150adb8c4b092 (diff)
downloadlinux-641bd5750517d2e5c128c566669c190857260693.tar.gz
linux-641bd5750517d2e5c128c566669c190857260693.zip
selinux: reject duplicate symbol values during policy load
The symbol index functions assign unconditionally, so two symbols that share a value silently overwrite each other and leave another value with no entry. Reject a value whose slot is already populated, for commons, classes, roles, types, users, sensitivities and categories; booleans already have their own "declared but not defined" check. Signed-off-by: Christian Göttsche <cgzones@googlemail.com> Reviewed-by: Stephen Smalley <stephen.smalley.work@gmail.com> Signed-off-by: Paul Moore <paul@paul-moore.com>
-rw-r--r--security/selinux/ss/policydb.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 7eeaf7076c52..6119df551f23 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -560,6 +560,9 @@ static int common_index(void *key, void *datum, void *datap)
if (!comdatum->value || comdatum->value > p->p_commons.nprim)
return -EINVAL;
+ if (p->sym_val_to_name[SYM_COMMONS][comdatum->value - 1])
+ return -EINVAL;
+
p->sym_val_to_name[SYM_COMMONS][comdatum->value - 1] = key;
return 0;
@@ -575,6 +578,9 @@ static int class_index(void *key, void *datum, void *datap)
if (!cladatum->value || cladatum->value > p->p_classes.nprim)
return -EINVAL;
+ if (p->class_val_to_struct[cladatum->value - 1])
+ return -EINVAL;
+
p->sym_val_to_name[SYM_CLASSES][cladatum->value - 1] = key;
p->class_val_to_struct[cladatum->value - 1] = cladatum;
return 0;
@@ -591,6 +597,9 @@ static int role_index(void *key, void *datum, void *datap)
role->bounds > p->p_roles.nprim)
return -EINVAL;
+ if (p->role_val_to_struct[role->value - 1])
+ return -EINVAL;
+
p->sym_val_to_name[SYM_ROLES][role->value - 1] = key;
p->role_val_to_struct[role->value - 1] = role;
return 0;
@@ -613,6 +622,8 @@ static int type_index(void *key, void *datum, void *datap)
}
if (typdatum->primary) {
+ if (p->type_val_to_struct[typdatum->value - 1])
+ return -EINVAL;
p->sym_val_to_name[SYM_TYPES][typdatum->value - 1] = key;
p->type_val_to_struct[typdatum->value - 1] = typdatum;
}
@@ -631,6 +642,9 @@ static int user_index(void *key, void *datum, void *datap)
usrdatum->bounds > p->p_users.nprim)
return -EINVAL;
+ if (p->user_val_to_struct[usrdatum->value - 1])
+ return -EINVAL;
+
p->sym_val_to_name[SYM_USERS][usrdatum->value - 1] = key;
p->user_val_to_struct[usrdatum->value - 1] = usrdatum;
return 0;
@@ -647,8 +661,11 @@ static int sens_index(void *key, void *datum, void *datap)
if (!levdatum->level.sens || levdatum->level.sens > p->p_levels.nprim)
return -EINVAL;
- if (!levdatum->isalias)
+ if (!levdatum->isalias) {
+ if (p->sym_val_to_name[SYM_LEVELS][levdatum->level.sens - 1])
+ return -EINVAL;
p->sym_val_to_name[SYM_LEVELS][levdatum->level.sens - 1] = key;
+ }
return 0;
}
@@ -664,8 +681,11 @@ static int cat_index(void *key, void *datum, void *datap)
if (!catdatum->value || catdatum->value > p->p_cats.nprim)
return -EINVAL;
- if (!catdatum->isalias)
+ if (!catdatum->isalias) {
+ if (p->sym_val_to_name[SYM_CATS][catdatum->value - 1])
+ return -EINVAL;
p->sym_val_to_name[SYM_CATS][catdatum->value - 1] = key;
+ }
return 0;
}