blob: 6e38705e782247a91e11f59246caea3131e43357 [file] [log] [blame]
From bc0dc0d86f86265db7b07f1b4f3a8766efec454d Mon Sep 17 00:00:00 2001
From: Ondrej Mosnacek <>
Date: Thu, 3 Oct 2019 15:59:22 +0200
Subject: [PATCH] selinux: fix context string corruption in convert_context()
commit 2a5243937c700ffe6a28e6557a4562a9ab0a17a4 upstream.
string_to_context_struct() may garble the context string, so we need to
copy back the contents again from the old context struct to avoid
storing the corrupted context.
Since string_to_context_struct() tokenizes (and therefore truncates) the
context string and we are later potentially copying it with kstrdup(),
this may eventually cause pieces of uninitialized kernel memory to be
disclosed to userspace (when copying to userspace based on the stored
length and not the null character).
How to reproduce on Fedora and similar:
# dnf install -y memcached
# systemctl start memcached
# semodule -d memcached
# load_policy
# load_policy
# systemctl stop memcached
# ausearch -m AVC
type=AVC msg=audit(1570090572.648:313): avc: denied { signal } for pid=1 comm="systemd" scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=process permissive=0 trawcon=73797374656D5F75007400000000000070BE6E847296FFFF726F6D000096FFFF76
Reported-by: Milos Malik <>
Fixes: ee1a84fdfeed ("selinux: overhaul sidtab to fix bug and improve performance")
Signed-off-by: Ondrej Mosnacek <>
Acked-by: Stephen Smalley <>
Signed-off-by: Paul Moore <>
Signed-off-by: Paul Gortmaker <>
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index d3f5568c1f60..3585ef8c4836 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1947,7 +1947,14 @@ static int convert_context(struct context *oldc, struct context *newc, void *p)
rc = string_to_context_struct(args->newp, NULL, s,
if (rc == -EINVAL) {
- /* Retain string representation for later mapping. */
+ /*
+ * Retain string representation for later mapping.
+ *
+ * IMPORTANT: We need to copy the contents of oldc->str
+ * back into s again because string_to_context_struct()
+ * may have garbled it.
+ */
+ memcpy(s, oldc->str, oldc->len);
newc->str = s;
newc->len = oldc->len;