summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorJohn Johansen <john.johansen@canonical.com>2019-05-26 06:42:23 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-06-25 11:35:54 +0800
commiteb2b0bf5c4a4afc4a761550af1da7da8444803b8 (patch)
treebaf0596e21d15c592547a02168159663263051d3 /security
parent1d08fe254fd6c6dc4b18d2390ed0d02eb2be85bb (diff)
downloadlinux-stable-eb2b0bf5c4a4afc4a761550af1da7da8444803b8.tar.gz
linux-stable-eb2b0bf5c4a4afc4a761550af1da7da8444803b8.tar.bz2
linux-stable-eb2b0bf5c4a4afc4a761550af1da7da8444803b8.zip
apparmor: fix PROFILE_MEDIATES for untrusted input
commit 23375b13f98c5464c2b4d15f983cc062940f1f4e upstream. While commit 11c236b89d7c2 ("apparmor: add a default null dfa") ensure every profile has a policy.dfa it does not resize the policy.start[] to have entries for every possible start value. Which means PROFILE_MEDIATES is not safe to use on untrusted input. Unforunately commit b9590ad4c4f2 ("apparmor: remove POLICY_MEDIATES_SAFE") did not take into account the start value usage. The input string in profile_query_cb() is user controlled and is not properly checked to be within the limited start[] entries, even worse it can't be as userspace policy is allowed to make us of entries types the kernel does not know about. This mean usespace can currently cause the kernel to access memory up to 240 entries beyond the start array bounds. Cc: stable@vger.kernel.org Fixes: b9590ad4c4f2 ("apparmor: remove POLICY_MEDIATES_SAFE") Signed-off-by: John Johansen <john.johansen@canonical.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'security')
-rw-r--r--security/apparmor/include/policy.h11
1 files changed, 10 insertions, 1 deletions
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
index ab64c6b5db5a..28c098fb6208 100644
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -214,7 +214,16 @@ static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p)
return labels_profile(aa_get_newest_label(&p->label));
}
-#define PROFILE_MEDIATES(P, T) ((P)->policy.start[(unsigned char) (T)])
+static inline unsigned int PROFILE_MEDIATES(struct aa_profile *profile,
+ unsigned char class)
+{
+ if (class <= AA_CLASS_LAST)
+ return profile->policy.start[class];
+ else
+ return aa_dfa_match_len(profile->policy.dfa,
+ profile->policy.start[0], &class, 1);
+}
+
static inline unsigned int PROFILE_MEDIATES_AF(struct aa_profile *profile,
u16 AF) {
unsigned int state = PROFILE_MEDIATES(profile, AA_CLASS_NET);