From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: stable@vger.kernel.org
Cc: "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
patches@lists.linux.dev,
"Christian Göttsche" <cgzones@googlemail.com>,
"Stephen Smalley" <stephen.smalley.work@gmail.com>,
"Paul Moore" <paul@paul-moore.com>,
"Wentao Guan" <guanwentao@uniontech.com>,
"Sasha Levin" <sashal@kernel.org>
Subject: [PATCH 7.1 08/76] selinux: more strict policy parsing
Date: Mon, 31 Aug 2026 15:33:40 +0200 [thread overview]
Message-ID: <20260831133359.580219011@linuxfoundation.org> (raw)
In-Reply-To: <20260831133359.185608553@linuxfoundation.org>
7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Göttsche <cgzones@googlemail.com>
[ Upstream commit 18fa21f10d008a0fc22565109c7d38f304295912 ]
Be more strict during parsing of policies and reject invalid values.
Add some error messages in the case of policy parse failures, to
enhance debugging, either on a malformed policy or a too strict check.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
[PM: fixed checkpatch.pl warnings, style problems]
Signed-off-by: Paul Moore <paul@paul-moore.com>
(cherry picked from commit 18fa21f10d008a0fc22565109c7d38f304295912)
Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
security/selinux/include/security.h | 1 +
security/selinux/ss/avtab.c | 35 ++++-
security/selinux/ss/avtab.h | 13 ++
security/selinux/ss/conditional.c | 18 +--
security/selinux/ss/constraint.h | 1 +
security/selinux/ss/policydb.c | 196 +++++++++++++++++++++++-----
security/selinux/ss/policydb.h | 23 +++-
security/selinux/ss/services.c | 6 +-
8 files changed, 233 insertions(+), 60 deletions(-)
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 0babb89921816..a74415e3afd3a 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -236,6 +236,7 @@ int security_read_policy(void **data, size_t *len);
int security_read_state_kernel(void **data, size_t *len);
int security_policycap_supported(unsigned int req_cap);
+/* Maximum supported number of permissions per class */
#define SEL_VEC_MAX 32
struct av_decision {
u32 allowed;
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index d12ca337e6498..fb67b36001566 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -316,7 +316,7 @@ int avtab_read_item(struct avtab *a, struct policy_file *fp, struct policydb *po
struct avtab_extended_perms xperms;
__le32 buf32[ARRAY_SIZE(xperms.perms.p)];
int rc;
- unsigned int set, vers = pol->policyvers;
+ unsigned int vers = pol->policyvers;
memset(&key, 0, sizeof(struct avtab_key));
memset(&datum, 0, sizeof(struct avtab_datum));
@@ -327,9 +327,12 @@ int avtab_read_item(struct avtab *a, struct policy_file *fp, struct policydb *po
pr_err("SELinux: avtab: truncated entry\n");
return rc;
}
+ /* Read five or more items: source type, target type,
+ * target class, AV type, and at least one datum.
+ */
items2 = le32_to_cpu(buf32[0]);
- if (items2 > ARRAY_SIZE(buf32)) {
- pr_err("SELinux: avtab: entry overflow\n");
+ if (items2 < 5 || items2 > ARRAY_SIZE(buf32)) {
+ pr_err("SELinux: avtab: invalid item count\n");
return -EINVAL;
}
rc = next_entry(buf32, fp, sizeof(u32) * items2);
@@ -358,6 +361,13 @@ int avtab_read_item(struct avtab *a, struct policy_file *fp, struct policydb *po
return -EINVAL;
}
+ if (!policydb_type_isvalid(pol, key.source_type) ||
+ !policydb_type_isvalid(pol, key.target_type) ||
+ !policydb_class_isvalid(pol, key.target_class)) {
+ pr_err("SELinux: avtab: invalid type or class\n");
+ return -EINVAL;
+ }
+
val = le32_to_cpu(buf32[items++]);
enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0;
@@ -376,6 +386,11 @@ int avtab_read_item(struct avtab *a, struct policy_file *fp, struct policydb *po
for (i = 0; i < ARRAY_SIZE(spec_order); i++) {
if (val & spec_order[i]) {
+ if (items >= items2) {
+ pr_err("SELinux: avtab: entry has too many items (%d/%d)\n",
+ items + 1, items2);
+ return -EINVAL;
+ }
key.specified = spec_order[i] | enabled;
datum.u.data = le32_to_cpu(buf32[items++]);
rc = insertf(a, &key, &datum, p);
@@ -411,9 +426,13 @@ int avtab_read_item(struct avtab *a, struct policy_file *fp, struct policydb *po
return -EINVAL;
}
- set = hweight16(key.specified & (AVTAB_XPERMS | AVTAB_TYPE | AVTAB_AV));
- if (!set || set > 1) {
- pr_err("SELinux: avtab: more than one specifier\n");
+ if (hweight16(key.specified & ~AVTAB_ENABLED) != 1) {
+ pr_err("SELinux: avtab: not exactly one specifier\n");
+ return -EINVAL;
+ }
+
+ if (key.specified & ~AVTAB_SPECIFIER_MASK) {
+ pr_err("SELinux: avtab: invalid specifier\n");
return -EINVAL;
}
@@ -438,6 +457,10 @@ int avtab_read_item(struct avtab *a, struct policy_file *fp, struct policydb *po
pr_err("SELinux: avtab: truncated entry\n");
return rc;
}
+ if (!avtab_is_valid_xperm_specified(xperms.specified))
+ pr_warn_once_policyload(pol,
+ "SELinux: avtab: unsupported xperm specifier %#x\n",
+ xperms.specified);
rc = next_entry(&xperms.driver, fp, sizeof(u8));
if (rc) {
pr_err("SELinux: avtab: truncated entry\n");
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h
index 850b3453f2598..1de4cce288a76 100644
--- a/security/selinux/ss/avtab.h
+++ b/security/selinux/ss/avtab.h
@@ -44,6 +44,7 @@ struct avtab_key {
AVTAB_XPERMS_DONTAUDIT)
#define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */
#define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */
+#define AVTAB_SPECIFIER_MASK (AVTAB_AV | AVTAB_TYPE | AVTAB_XPERMS | AVTAB_ENABLED)
u16 specified; /* what field is specified */
};
@@ -68,6 +69,18 @@ struct avtab_extended_perms {
struct extended_perms_data perms;
};
+static inline bool avtab_is_valid_xperm_specified(u8 specified)
+{
+ switch (specified) {
+ case AVTAB_XPERMS_IOCTLFUNCTION:
+ case AVTAB_XPERMS_IOCTLDRIVER:
+ case AVTAB_XPERMS_NLMSG:
+ return true;
+ default:
+ return false;
+ }
+}
+
struct avtab_datum {
union {
u32 data; /* access vector or type value */
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index 824c3f8961518..f0a9866f01659 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -199,19 +199,12 @@ int cond_index_bool(void *key, void *datum, void *datap)
return 0;
}
-static int bool_isvalid(struct cond_bool_datum *b)
-{
- if (!(b->state == 0 || b->state == 1))
- return 0;
- return 1;
-}
-
int cond_read_bool(struct policydb *p, struct symtab *s, struct policy_file *fp)
{
char *key = NULL;
struct cond_bool_datum *booldatum;
__le32 buf[3];
- u32 len;
+ u32 len, val;
int rc;
booldatum = kzalloc_obj(*booldatum);
@@ -223,11 +216,12 @@ int cond_read_bool(struct policydb *p, struct symtab *s, struct policy_file *fp)
goto err;
booldatum->value = le32_to_cpu(buf[0]);
- booldatum->state = le32_to_cpu(buf[1]);
+ val = le32_to_cpu(buf[1]);
rc = -EINVAL;
- if (!bool_isvalid(booldatum))
+ if (!val_is_boolean(val))
goto err;
+ booldatum->state = (int)val;
len = le32_to_cpu(buf[2]);
@@ -241,6 +235,7 @@ int cond_read_bool(struct policydb *p, struct symtab *s, struct policy_file *fp)
return 0;
err:
+ pr_err("SELinux: conditional: failed to read boolean\n");
cond_destroy_bool(key, booldatum, NULL);
return rc;
}
@@ -362,7 +357,8 @@ static int expr_node_isvalid(struct policydb *p, struct cond_expr_node *expr)
return 0;
}
- if (expr->boolean > p->p_bools.nprim) {
+ if (expr->expr_type == COND_BOOL &&
+ (expr->boolean == 0 || expr->boolean > p->p_bools.nprim)) {
pr_err("SELinux: conditional expressions uses unknown bool.\n");
return 0;
}
diff --git a/security/selinux/ss/constraint.h b/security/selinux/ss/constraint.h
index 203033cfad672..1d75a8a044df9 100644
--- a/security/selinux/ss/constraint.h
+++ b/security/selinux/ss/constraint.h
@@ -50,6 +50,7 @@ struct constraint_expr {
u32 op; /* operator */
struct ebitmap names; /* names */
+ /* internally unused, only forwarded via policydb_write() */
struct type_set *type_names;
struct constraint_expr *next; /* next expression */
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index d36c34cdb5d98..ef5bd0736748c 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -638,13 +638,11 @@ static int sens_index(void *key, void *datum, void *datap)
levdatum = datum;
p = datap;
- if (!levdatum->isalias) {
- if (!levdatum->level.sens ||
- levdatum->level.sens > p->p_levels.nprim)
- return -EINVAL;
+ if (!levdatum->level.sens || levdatum->level.sens > p->p_levels.nprim)
+ return -EINVAL;
+ if (!levdatum->isalias)
p->sym_val_to_name[SYM_LEVELS][levdatum->level.sens - 1] = key;
- }
return 0;
}
@@ -657,12 +655,11 @@ static int cat_index(void *key, void *datum, void *datap)
catdatum = datum;
p = datap;
- if (!catdatum->isalias) {
- if (!catdatum->value || catdatum->value > p->p_cats.nprim)
- return -EINVAL;
+ if (!catdatum->value || catdatum->value > p->p_cats.nprim)
+ return -EINVAL;
+ if (!catdatum->isalias)
p->sym_val_to_name[SYM_CATS][catdatum->value - 1] = key;
- }
return 0;
}
@@ -1159,6 +1156,9 @@ static int perm_read(struct policydb *p, struct symtab *s, struct policy_file *f
len = le32_to_cpu(buf[0]);
perdatum->value = le32_to_cpu(buf[1]);
+ rc = -EINVAL;
+ if (perdatum->value < 1 || perdatum->value > SEL_VEC_MAX)
+ goto bad;
rc = str_read(&key, GFP_KERNEL, fp, len);
if (rc)
@@ -1193,6 +1193,9 @@ static int common_read(struct policydb *p, struct symtab *s, struct policy_file
len = le32_to_cpu(buf[0]);
comdatum->value = le32_to_cpu(buf[1]);
nel = le32_to_cpu(buf[3]);
+ rc = -EINVAL;
+ if (nel > SEL_VEC_MAX)
+ goto bad;
rc = symtab_init(&comdatum->permissions, nel);
if (rc)
@@ -1342,7 +1345,7 @@ static int class_read(struct policydb *p, struct symtab *s, struct policy_file *
char *key = NULL;
struct class_datum *cladatum;
__le32 buf[6];
- u32 i, len, len2, ncons, nel;
+ u32 i, len, len2, ncons, nel, val;
int rc;
cladatum = kzalloc_obj(*cladatum);
@@ -1355,8 +1358,16 @@ static int class_read(struct policydb *p, struct symtab *s, struct policy_file *
len = le32_to_cpu(buf[0]);
len2 = le32_to_cpu(buf[1]);
- cladatum->value = le32_to_cpu(buf[2]);
nel = le32_to_cpu(buf[4]);
+ rc = -EINVAL;
+ if (nel > SEL_VEC_MAX)
+ goto bad;
+
+ val = le32_to_cpu(buf[2]);
+ rc = -EINVAL;
+ if (val > U16_MAX)
+ goto bad;
+ cladatum->value = val;
rc = symtab_init(&cladatum->permissions, nel);
if (rc)
@@ -1424,16 +1435,59 @@ static int class_read(struct policydb *p, struct symtab *s, struct policy_file *
if (rc)
goto bad;
- cladatum->default_user = le32_to_cpu(buf[0]);
- cladatum->default_role = le32_to_cpu(buf[1]);
- cladatum->default_range = le32_to_cpu(buf[2]);
+ rc = -EINVAL;
+ val = le32_to_cpu(buf[0]);
+ switch (val) {
+ case 0:
+ case DEFAULT_SOURCE:
+ case DEFAULT_TARGET:
+ cladatum->default_user = val;
+ break;
+ default:
+ goto bad;
+ }
+ val = le32_to_cpu(buf[1]);
+ switch (val) {
+ case 0:
+ case DEFAULT_SOURCE:
+ case DEFAULT_TARGET:
+ cladatum->default_role = val;
+ break;
+ default:
+ goto bad;
+ }
+ val = le32_to_cpu(buf[2]);
+ switch (val) {
+ case 0:
+ case DEFAULT_SOURCE_LOW:
+ case DEFAULT_SOURCE_HIGH:
+ case DEFAULT_SOURCE_LOW_HIGH:
+ case DEFAULT_TARGET_LOW:
+ case DEFAULT_TARGET_HIGH:
+ case DEFAULT_TARGET_LOW_HIGH:
+ case DEFAULT_GLBLUB:
+ cladatum->default_range = val;
+ break;
+ default:
+ goto bad;
+ }
}
if (p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) {
rc = next_entry(buf, fp, sizeof(u32) * 1);
if (rc)
goto bad;
- cladatum->default_type = le32_to_cpu(buf[0]);
+ rc = -EINVAL;
+ val = le32_to_cpu(buf[0]);
+ switch (val) {
+ case 0:
+ case DEFAULT_TARGET:
+ case DEFAULT_SOURCE:
+ cladatum->default_type = val;
+ break;
+ default:
+ goto bad;
+ }
}
rc = symtab_insert(s, key, cladatum);
@@ -1443,6 +1497,8 @@ static int class_read(struct policydb *p, struct symtab *s, struct policy_file *
return 0;
bad:
cls_destroy(key, cladatum, NULL);
+ if (rc)
+ pr_err("SELinux: invalid class\n");
return rc;
}
@@ -1634,7 +1690,7 @@ static int sens_read(struct policydb *p, struct symtab *s, struct policy_file *f
struct level_datum *levdatum;
int rc;
__le32 buf[2];
- u32 len;
+ u32 len, val;
levdatum = kzalloc_obj(*levdatum);
if (!levdatum)
@@ -1645,7 +1701,11 @@ static int sens_read(struct policydb *p, struct symtab *s, struct policy_file *f
goto bad;
len = le32_to_cpu(buf[0]);
- levdatum->isalias = le32_to_cpu(buf[1]);
+ val = le32_to_cpu(buf[1]);
+ rc = -EINVAL;
+ if (!val_is_boolean(val))
+ goto bad;
+ levdatum->isalias = val;
rc = str_read(&key, GFP_KERNEL, fp, len);
if (rc)
@@ -1661,6 +1721,8 @@ static int sens_read(struct policydb *p, struct symtab *s, struct policy_file *f
return 0;
bad:
sens_destroy(key, levdatum, NULL);
+ if (rc)
+ pr_err("SELinux: invalid sensitivity\n");
return rc;
}
@@ -1670,7 +1732,7 @@ static int cat_read(struct policydb *p, struct symtab *s, struct policy_file *fp
struct cat_datum *catdatum;
int rc;
__le32 buf[3];
- u32 len;
+ u32 len, val;
catdatum = kzalloc_obj(*catdatum);
if (!catdatum)
@@ -1682,7 +1744,11 @@ static int cat_read(struct policydb *p, struct symtab *s, struct policy_file *fp
len = le32_to_cpu(buf[0]);
catdatum->value = le32_to_cpu(buf[1]);
- catdatum->isalias = le32_to_cpu(buf[2]);
+ val = le32_to_cpu(buf[2]);
+ rc = -EINVAL;
+ if (!val_is_boolean(val))
+ goto bad;
+ catdatum->isalias = val;
rc = str_read(&key, GFP_KERNEL, fp, len);
if (rc)
@@ -1694,6 +1760,8 @@ static int cat_read(struct policydb *p, struct symtab *s, struct policy_file *fp
return 0;
bad:
cat_destroy(key, catdatum, NULL);
+ if (rc)
+ pr_err("SELinux: invalid category\n");
return rc;
}
@@ -1875,7 +1943,7 @@ static int range_read(struct policydb *p, struct policy_file *fp)
struct mls_range *r = NULL;
int rc;
__le32 buf[2];
- u32 i, nel;
+ u32 i, nel, val;
if (p->policyvers < POLICYDB_VERSION_MLS)
return 0;
@@ -1906,7 +1974,11 @@ static int range_read(struct policydb *p, struct policy_file *fp)
rc = next_entry(buf, fp, sizeof(u32));
if (rc)
goto out;
- rt->target_class = le32_to_cpu(buf[0]);
+ rc = -EINVAL;
+ val = le32_to_cpu(buf[0]);
+ if (val > U16_MAX)
+ goto out;
+ rt->target_class = val;
} else
rt->target_class = p->process_class;
@@ -1943,6 +2015,8 @@ static int range_read(struct policydb *p, struct policy_file *fp)
out:
kfree(rt);
kfree(r);
+ if (rc)
+ pr_err("SELinux: invalid range\n");
return rc;
}
@@ -1951,7 +2025,7 @@ static int filename_trans_read_helper_compat(struct policydb *p, struct policy_f
struct filename_trans_key key, *ft = NULL;
struct filename_trans_datum *last, *datum = NULL;
char *name = NULL;
- u32 len, stype, otype;
+ u32 len, stype, otype, val;
__le32 buf[4];
int rc;
@@ -1970,9 +2044,17 @@ static int filename_trans_read_helper_compat(struct policydb *p, struct policy_f
if (rc)
goto out;
+ rc = -EINVAL;
stype = le32_to_cpu(buf[0]);
+ if (!policydb_type_isvalid(p, stype))
+ goto out;
key.ttype = le32_to_cpu(buf[1]);
- key.tclass = le32_to_cpu(buf[2]);
+ if (!policydb_type_isvalid(p, key.ttype))
+ goto out;
+ val = le32_to_cpu(buf[2]);
+ if (val > U16_MAX || !policydb_class_isvalid(p, val))
+ goto out;
+ key.tclass = val;
key.name = name;
otype = le32_to_cpu(buf[3]);
@@ -2028,6 +2110,9 @@ static int filename_trans_read_helper_compat(struct policydb *p, struct policy_f
kfree(ft);
kfree(name);
kfree(datum);
+
+ if (rc)
+ pr_err("SELinux: invalid compat filename transition\n");
return rc;
}
@@ -2036,7 +2121,7 @@ static int filename_trans_read_helper(struct policydb *p, struct policy_file *fp
struct filename_trans_key *ft = NULL;
struct filename_trans_datum **dst, *datum, *first = NULL;
char *name = NULL;
- u32 len, ttype, ndatum, i;
+ u32 len, ttype, ndatum, i, val;
u16 tclass;
__le32 buf[3];
int rc;
@@ -2056,8 +2141,15 @@ static int filename_trans_read_helper(struct policydb *p, struct policy_file *fp
if (rc)
goto out;
+ rc = -EINVAL;
ttype = le32_to_cpu(buf[0]);
- tclass = le32_to_cpu(buf[1]);
+ if (!policydb_type_isvalid(p, ttype))
+ goto out;
+ val = le32_to_cpu(buf[1]);
+ rc = -EINVAL;
+ if (val > U16_MAX || !policydb_class_isvalid(p, val))
+ goto out;
+ tclass = val;
ndatum = le32_to_cpu(buf[2]);
if (ndatum == 0) {
@@ -2087,6 +2179,10 @@ static int filename_trans_read_helper(struct policydb *p, struct policy_file *fp
datum->otype = le32_to_cpu(buf[0]);
+ rc = -EINVAL;
+ if (!policydb_type_isvalid(p, datum->otype))
+ goto out;
+
dst = &datum->next;
}
@@ -2118,6 +2214,9 @@ static int filename_trans_read_helper(struct policydb *p, struct policy_file *fp
ebitmap_destroy(&datum->stypes);
kfree(datum);
}
+
+ if (rc)
+ pr_err("SELinux: invalid filename transition\n");
return rc;
}
@@ -2165,7 +2264,7 @@ static int filename_trans_read(struct policydb *p, struct policy_file *fp)
static int genfs_read(struct policydb *p, struct policy_file *fp)
{
int rc;
- u32 i, j, nel, nel2, len, len2;
+ u32 i, j, nel, nel2, len, len2, val;
__le32 buf[1];
struct ocontext *l, *c;
struct ocontext *newc = NULL;
@@ -2235,7 +2334,11 @@ static int genfs_read(struct policydb *p, struct policy_file *fp)
if (rc)
goto out;
- newc->v.sclass = le32_to_cpu(buf[0]);
+ rc = -EINVAL;
+ val = le32_to_cpu(buf[0]);
+ if (val > U16_MAX || (val != 0 && !policydb_class_isvalid(p, val)))
+ goto out;
+ newc->v.sclass = val;
rc = context_read_and_validate(&newc->context[0], p,
fp);
if (rc)
@@ -2272,6 +2375,9 @@ static int genfs_read(struct policydb *p, struct policy_file *fp)
}
ocontext_destroy(newc, OCON_FSUSE);
+ if (rc)
+ pr_err("SELinux: invalid genfs\n");
+
return rc;
}
@@ -2280,7 +2386,7 @@ static int ocontext_read(struct policydb *p,
{
int rc;
unsigned int i;
- u32 j, nel, len;
+ u32 j, nel, len, val;
__be64 prefixbuf[1];
__le32 buf[3];
struct ocontext *l, *c;
@@ -2344,11 +2450,25 @@ static int ocontext_read(struct policydb *p,
rc = next_entry(buf, fp, sizeof(u32) * 3);
if (rc)
goto out;
- c->u.port.protocol = le32_to_cpu(buf[0]);
- c->u.port.low_port = le32_to_cpu(buf[1]);
- c->u.port.high_port = le32_to_cpu(buf[2]);
- rc = context_read_and_validate(&c->context[0],
- p, fp);
+
+ rc = -EINVAL;
+ val = le32_to_cpu(buf[0]);
+ if (val > U8_MAX)
+ goto out;
+ c->u.port.protocol = val;
+ val = le32_to_cpu(buf[1]);
+ if (val > U16_MAX)
+ goto out;
+ c->u.port.low_port = val;
+ val = le32_to_cpu(buf[2]);
+ if (val > U16_MAX)
+ goto out;
+ c->u.port.high_port = val;
+ if (c->u.port.low_port == 0 ||
+ c->u.port.low_port > c->u.port.high_port)
+ goto out;
+
+ rc = context_read_and_validate(&c->context[0], p, fp);
if (rc)
goto out;
break;
@@ -2466,6 +2586,8 @@ static int ocontext_read(struct policydb *p,
}
rc = 0;
out:
+ if (rc)
+ pr_err("SELinux: invalid ocon\n");
return rc;
}
@@ -2480,7 +2602,7 @@ int policydb_read(struct policydb *p, struct policy_file *fp)
struct role_trans_datum *rtd = NULL;
int rc;
__le32 buf[4];
- u32 i, j, len, nprim, nel, perm;
+ u32 i, j, len, nprim, nel, perm, val;
char *policydb_str;
const struct policydb_compat_info *info;
@@ -2672,7 +2794,11 @@ int policydb_read(struct policydb *p, struct policy_file *fp)
rc = next_entry(buf, fp, sizeof(u32));
if (rc)
goto bad;
- rtk->tclass = le32_to_cpu(buf[0]);
+ rc = -EINVAL;
+ val = le32_to_cpu(buf[0]);
+ if (val > U16_MAX)
+ goto bad;
+ rtk->tclass = val;
} else
rtk->tclass = p->process_class;
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index a49275d1168d8..20b834581106a 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -74,7 +74,7 @@ struct class_datum {
/* Role attributes */
struct role_datum {
u32 value; /* internal role value */
- u32 bounds; /* boundary of role */
+ u32 bounds; /* boundary of role, 0 for none */
struct ebitmap dominates; /* set of roles dominated by this role */
struct ebitmap types; /* set of authorized types for role */
};
@@ -110,7 +110,8 @@ struct role_allow {
/* Type attributes */
struct type_datum {
u32 value; /* internal type value */
- u32 bounds; /* boundary of type */
+ u32 bounds; /* boundary of type, 0 for none */
+ /* internally unused, only forwarded via policydb_write() */
unsigned char primary; /* primary name? */
unsigned char attribute; /* attribute ?*/
};
@@ -118,7 +119,7 @@ struct type_datum {
/* User attributes */
struct user_datum {
u32 value; /* internal user value */
- u32 bounds; /* bounds of user */
+ u32 bounds; /* bounds of user, 0 for none */
struct ebitmap roles; /* set of authorized roles for user */
struct mls_range range; /* MLS range (min - max) for user */
struct mls_level dfltlevel; /* default login MLS level for user */
@@ -195,7 +196,7 @@ struct ocontext {
} ibendport;
} u;
union {
- u16 sclass; /* security class for genfs */
+ u16 sclass; /* security class for genfs (can be 0 for wildcard) */
u32 behavior; /* labeling behavior for fs_use */
} v;
struct context context[2]; /* security context(s) */
@@ -388,9 +389,23 @@ static inline char *sym_name(struct policydb *p, unsigned int sym_num,
return p->sym_val_to_name[sym_num][element_nr];
}
+static inline bool val_is_boolean(u32 value)
+{
+ return value == 0 || value == 1;
+}
+
extern int str_read(char **strp, gfp_t flags, struct policy_file *fp, u32 len);
extern u16 string_to_security_class(struct policydb *p, const char *name);
extern u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name);
+#define pr_warn_once_policyload(policy, fmt, ...) \
+ do { \
+ static const void *prev_policy__; \
+ if (prev_policy__ != policy) { \
+ pr_warn(fmt, ##__VA_ARGS__); \
+ prev_policy__ = policy; \
+ } \
+ } while (0)
+
#endif /* _SS_POLICYDB_H_ */
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index e48e5204f8a1c..016863f950846 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -446,8 +446,6 @@ static int dump_masked_av_helper(void *k, void *d, void *args)
struct perm_datum *pdatum = d;
char **permission_names = args;
- BUG_ON(pdatum->value < 1 || pdatum->value > 32);
-
permission_names[pdatum->value - 1] = (char *)k;
return 0;
@@ -466,7 +464,7 @@ static void security_dump_masked_av(struct policydb *policydb,
char *tclass_name;
char *scontext_name = NULL;
char *tcontext_name = NULL;
- char *permission_names[32];
+ char *permission_names[SEL_VEC_MAX];
int index;
u32 length;
bool need_comma = false;
@@ -507,7 +505,7 @@ static void security_dump_masked_av(struct policydb *policydb,
"scontext=%s tcontext=%s tclass=%s perms=",
reason, scontext_name, tcontext_name, tclass_name);
- for (index = 0; index < 32; index++) {
+ for (index = 0; index < SEL_VEC_MAX; index++) {
u32 mask = (1 << index);
if ((mask & permissions) == 0)
--
2.53.0
next prev parent reply other threads:[~2026-08-31 13:42 UTC|newest]
Thread overview: 85+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-31 13:33 [PATCH 7.1 00/76] 7.1.13-rc1 review Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 01/76] bpf: reject overlarge global subprog argument sizes Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 02/76] RDMA/rxe: Fix responder UAF on IB_QP_MAX_DEST_RD_ATOMIC modify_qp Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 03/76] RDMA/rxe: Fix OOB in free_rd_atomic_resources() Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 04/76] KVM: x86/mmu: Check write tracking in all address spaces Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 05/76] nvme-tcp: fix usage of page_frag_cache Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 06/76] Revert "selinux: reject a permission value exceeding the class permission count" Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 07/76] selinux: use u16 for security classes Greg Kroah-Hartman
2026-08-31 13:33 ` Greg Kroah-Hartman [this message]
2026-08-31 13:33 ` [PATCH 7.1 09/76] selinux: reject a permission value exceeding the class permission count Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 10/76] selinux: require a classs permission values to cover its " Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 11/76] selinux: switch two allocations to use kzalloc_objs() Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 12/76] ext4: export converted block count from ext4_convert_unwritten_extents() Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 13/76] ext4: protect WRITE_ZEROES written extents with orphan list Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 14/76] ext4: move partial block zeroing earlier in ext4_zero_range() Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 15/76] ext4: write back partial-zeroed edges in WRITE_ZEROES Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 16/76] ext4: track partial-zero outcome per edge in ext4_zero_partial_blocks() Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 17/76] ext4: zero out whole block for clean edges in WRITE_ZEROES Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 18/76] fpga: dfl: fme: add error handling Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 19/76] accessibility: speakup: unregister tty ldisc on later init failures Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 20/76] usb: xhci: Handle bogus TRB pointers in Missed Service Error events Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 21/76] usb: xhci: Handle USB3 port events when there is one roothub Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 22/76] usb: xhci: bail out of setup if the controller is inaccessible Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 23/76] xhci: dbgtty: Fix unregister on tty_register_driver() failure Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 24/76] xhci: dbgtty: Fix unregister on tty_alloc_driver() failure Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 25/76] fuse: fix invalidate lock leak on setattr writeback failure Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 26/76] fuse: fix invalidate lock leak on open O_TRUNC DAX failure Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.1 27/76] usb: usbtest: disable dynamic ID support Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 28/76] usb: gadget: f_tcm: keep port count until LUN teardown completes Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 29/76] KVM: SEV: Drop FOLL_WRITE for encrypted region registration Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 30/76] KVM: SEV: Track the GPA of the guest-controlled VMSA used for SNP guests Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 31/76] KVM: SEV: Extract loading of guest-provided VMSA to a separate helper Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 32/76] KVM: SEV: Mark vCPU RUNNABLE after AP_CREATE, even if VMSA is unusable Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 33/76] KVM: SEV: Wire up kvm_x86_ops.gmem_xxx() if and only if CONFIG_KVM_AMD_SEV=y Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 34/76] tls: device: fix out-of-bounds write in tls_append_frag() Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 35/76] gtp: serialize PDP context updates Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 36/76] net/tcp: fix TCP-AO key deletion in VRFs Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 37/76] tcp: fix AO info use-after-free in tcp_ao_connect_init() Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 38/76] net/tcp-ao: fix use-after-free of current_key on reconnect to another peer Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 39/76] net: advertise TCP MSS from the configured MTU, not the learned PMTU Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 40/76] xfrm: espintcp: fix UAF during close Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 41/76] tcp: clamp route advmss to TCP_MIN_MSS Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 42/76] xfrm: drop ESP-in-TCP packets with no ingress device Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 43/76] xfrm: avoid lock inversion in nat keepalive work Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 44/76] xfrm: ah6: validate routing header segments_left Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 45/76] xfrm: fix xfrm_state_construct() auth-trunc leak Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 46/76] xfrm: bound nat keepalive state collection Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 47/76] net: bridge: mcast: fix use-after-free of a master VLANs multicast context Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 48/76] net/packet: defer vmalloc TX_RING free until skbs finish Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 49/76] ipv6: seg6: clear IPv4 control block on IPIP decapsulation Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 50/76] batman-adv: reject unrepresentable multicast TVLV offsets Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 51/76] vxlan: keep the last remote linked during FDB flush Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 52/76] netfilter: nft_set_pipapo_avx2: add missing vzeroupper Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 53/76] netfilter: nf_tables: dont queue packet path object notifications Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 54/76] mm/swap: reject swapon() on filesystem-level encrypted files Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 55/76] kunit: irq: Continue increasing hrtimer interval for longer Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 56/76] crypto: virtio - bound the akcipher result length Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 57/76] crypto: qcom-rng - Enable clock in hwrng case Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 58/76] crypto: qcom-rng - Remove crypto_rng interface Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 59/76] crypto: qcom-rng - Allow zero as a random number Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 60/76] crypto: atmel-tdes - use scatterlist length before DMA mapping Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 61/76] crypto: krb5 - use kfree_sensitive() for derived key buffers Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 62/76] crypto: qce - fix CCM AAD buffer underallocation Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 63/76] crypto: iaa - fall back to software for multi-entry scatterlists Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 64/76] crypto: mxs-dcp - fix source scatterlist length access Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 65/76] crypto: qce - Remove unsafe/deprecated algorithms Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 66/76] KVM: s390: vsie: zero stale crypto bits Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 67/76] usb: core: Add lock to usb_wakeup_notification() Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 68/76] usb: core: Strengthen error handling in hub_hub_status() Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 69/76] ALSA: usb-audio: Fix sample rates for PreSonus AudioBox USB Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 70/76] ALSA: usb-audio: fix OOB write in snd_usbmidi_novation_output() Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 71/76] ALSA: usb-audio: Complete cleanup after system-resume errors Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 72/76] USB: serial: option: fix slab OOB read in interrupt URB callback Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 73/76] USB: serial: spcp8x5: drop broken carrier detect support Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 74/76] USB: c67x00: fix use-after-free in c67x00_add_iso_urb() Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 75/76] wifi: mt76: mt7925: ensure tx headroom in usb_sdio_tx_prepare_skb Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.1 76/76] usb: usbfs: fix use-after-free of usb_device in usbdev_release() Greg Kroah-Hartman
2026-08-31 19:12 ` [PATCH 7.1 00/76] 7.1.13-rc1 review Brett A C Sheffield
2026-09-01 0:45 ` Florian Fainelli
2026-09-01 7:44 ` Barry K. Nathan
2026-09-01 8:42 ` Pavel Machek
2026-09-01 12:06 ` Peter Schneider
2026-09-01 16:44 ` Shuah Khan
2026-09-01 22:59 ` Ron Economos
2026-09-02 1:55 ` Justin Forbes
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260831133359.580219011@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=cgzones@googlemail.com \
--cc=guanwentao@uniontech.com \
--cc=patches@lists.linux.dev \
--cc=paul@paul-moore.com \
--cc=sashal@kernel.org \
--cc=stable@vger.kernel.org \
--cc=stephen.smalley.work@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox