[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250511173055.406906-14-cgoettsche@seltendoof.de>
Date: Sun, 11 May 2025 19:30:14 +0200
From: Christian Göttsche <cgoettsche@...tendoof.de>
To: selinux@...r.kernel.org
Cc: Christian Göttsche <cgzones@...glemail.com>,
Paul Moore <paul@...l-moore.com>,
Stephen Smalley <stephen.smalley.work@...il.com>,
Ondrej Mosnacek <omosnace@...hat.com>,
linux-kernel@...r.kernel.org,
Thiébaud Weksteen <tweek@...gle.com>,
Casey Schaufler <casey@...aufler-ca.com>,
Canfeng Guo <guocanfeng@...ontech.com>,
Takaya Saeki <takayas@...omium.org>
Subject: [PATCH v3 14/14] selinux: harden MLS context string generation against overflows
From: Christian Göttsche <cgzones@...glemail.com>
Check the length accumulator for the MLS component of security contexts
does not overflow in mls_compute_context_len() resulting in
out-of-buffer writes in mls_sid_to_context().
Signed-off-by: Christian Göttsche <cgzones@...glemail.com>
---
v3: add patch
---
security/selinux/ss/mls.c | 18 +++++++++-----
security/selinux/ss/services.c | 43 +++++++++++++++++++++++++++++-----
2 files changed, 49 insertions(+), 12 deletions(-)
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 3cd36e2015fa..aa25724f0b0f 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -42,7 +42,8 @@ int mls_compute_context_len(struct policydb *p, struct context *context)
len = 1; /* for the beginning ":" */
for (l = 0; l < 2; l++) {
u32 index_sens = context->range.level[l].sens;
- len += strlen(sym_name(p, SYM_LEVELS, index_sens - 1));
+ if (check_add_overflow(len, strlen(sym_name(p, SYM_LEVELS, index_sens - 1)), &len))
+ return -EOVERFLOW;
/* categories */
head = -2;
@@ -54,24 +55,29 @@ int mls_compute_context_len(struct policydb *p, struct context *context)
/* one or more negative bits are skipped */
if (head != prev) {
nm = sym_name(p, SYM_CATS, prev);
- len += strlen(nm) + 1;
+ if (check_add_overflow(len, strlen(nm) + 1, &len))
+ return -EOVERFLOW;
}
nm = sym_name(p, SYM_CATS, i);
- len += strlen(nm) + 1;
+ if (check_add_overflow(len, strlen(nm) + 1, &len))
+ return -EOVERFLOW;
head = i;
}
prev = i;
}
if (prev != head) {
nm = sym_name(p, SYM_CATS, prev);
- len += strlen(nm) + 1;
+ if (check_add_overflow(len, strlen(nm) + 1, &len))
+ return -EOVERFLOW;
}
if (l == 0) {
if (mls_level_eq(&context->range.level[0],
&context->range.level[1]))
break;
- else
- len++;
+ else {
+ if (check_add_overflow(len, 1, &len))
+ return -EOVERFLOW;
+ }
}
}
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 464a4663c993..dc6dce2eb7d2 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1247,10 +1247,12 @@ static int context_struct_to_string(struct policydb *p,
char **scontext, u32 *scontext_len)
{
char *scontextp;
+ size_t len;
+ int mls_len;
if (scontext)
*scontext = NULL;
- *scontext_len = 0;
+ len = 0;
if (context->len) {
*scontext_len = context->len;
@@ -1263,16 +1265,45 @@ static int context_struct_to_string(struct policydb *p,
}
/* Compute the size of the context. */
- *scontext_len += strlen(sym_name(p, SYM_USERS, context->user - 1)) + 1;
- *scontext_len += strlen(sym_name(p, SYM_ROLES, context->role - 1)) + 1;
- *scontext_len += strlen(sym_name(p, SYM_TYPES, context->type - 1)) + 1;
- *scontext_len += mls_compute_context_len(p, context);
+ len += strlen(sym_name(p, SYM_USERS, context->user - 1)) + 1;
+ len += strlen(sym_name(p, SYM_ROLES, context->role - 1)) + 1;
+ len += strlen(sym_name(p, SYM_TYPES, context->type - 1)) + 1;
+
+ mls_len = mls_compute_context_len(p, context);
+ if (unlikely(mls_len < 0)) {
+ pr_warn_ratelimited("SELinux: %s: MLS security context component too large [%s:%s:%s[:[%s:%d]-[%s:%d]]]\n",
+ __func__,
+ sym_name(p, SYM_USERS, context->user - 1),
+ sym_name(p, SYM_ROLES, context->role - 1),
+ sym_name(p, SYM_TYPES, context->type - 1),
+ sym_name(p, SYM_LEVELS, context->range.level[0].sens - 1),
+ ebitmap_length(&context->range.level[0].cat),
+ sym_name(p, SYM_LEVELS, context->range.level[1].sens - 1),
+ ebitmap_length(&context->range.level[1].cat));
+ return -EOVERFLOW;
+ }
+
+ if (unlikely(check_add_overflow(len, mls_len, &len) || len > CONTEXT_MAXLENGTH)) {
+ pr_warn_ratelimited("SELinux: %s: security context string of length %zu too large [%s:%s:%s[:[%s:%d]-[%s:%d]]]\n",
+ __func__,
+ len,
+ sym_name(p, SYM_USERS, context->user - 1),
+ sym_name(p, SYM_ROLES, context->role - 1),
+ sym_name(p, SYM_TYPES, context->type - 1),
+ sym_name(p, SYM_LEVELS, context->range.level[0].sens - 1),
+ ebitmap_length(&context->range.level[0].cat),
+ sym_name(p, SYM_LEVELS, context->range.level[1].sens - 1),
+ ebitmap_length(&context->range.level[1].cat));
+ return -EOVERFLOW;
+ }
+
+ *scontext_len = len;
if (!scontext)
return 0;
/* Allocate space for the context; caller must free this space. */
- scontextp = kmalloc(*scontext_len, GFP_ATOMIC);
+ scontextp = kmalloc(len, GFP_ATOMIC);
if (!scontextp)
return -ENOMEM;
*scontext = scontextp;
--
2.49.0
Powered by blists - more mailing lists