]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.19.41/selinux-avoid-silent-denials-in-permissive-mode-under-rcu-walk.patch
5.1-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.19.41 / selinux-avoid-silent-denials-in-permissive-mode-under-rcu-walk.patch
CommitLineData
efa860ba
GKH
1From 3a28cff3bd4bf43f02be0c4e7933aebf3dc8197e Mon Sep 17 00:00:00 2001
2From: Stephen Smalley <sds@tycho.nsa.gov>
3Date: Wed, 12 Dec 2018 10:10:55 -0500
4Subject: selinux: avoid silent denials in permissive mode under RCU walk
5
6From: Stephen Smalley <sds@tycho.nsa.gov>
7
8commit 3a28cff3bd4bf43f02be0c4e7933aebf3dc8197e upstream.
9
10commit 0dc1ba24f7fff6 ("SELINUX: Make selinux cache VFS RCU walks safe")
11results in no audit messages at all if in permissive mode because the
12cache is updated during the rcu walk and thus no denial occurs on
13the subsequent ref walk. Fix this by not updating the cache when
14performing a non-blocking permission check. This only affects search
15and symlink read checks during rcu walk.
16
17Fixes: 0dc1ba24f7fff6 ("SELINUX: Make selinux cache VFS RCU walks safe")
18Reported-by: BMK <bmktuwien@gmail.com>
19Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
20Signed-off-by: Paul Moore <paul@paul-moore.com>
21Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
22
23---
24 security/selinux/avc.c | 23 +++++++++++++++++++++--
25 security/selinux/hooks.c | 4 +++-
26 security/selinux/include/avc.h | 1 +
27 3 files changed, 25 insertions(+), 3 deletions(-)
28
29--- a/security/selinux/avc.c
30+++ b/security/selinux/avc.c
31@@ -838,6 +838,7 @@ out:
32 * @ssid,@tsid,@tclass : identifier of an AVC entry
33 * @seqno : sequence number when decision was made
34 * @xpd: extended_perms_decision to be added to the node
35+ * @flags: the AVC_* flags, e.g. AVC_NONBLOCKING, AVC_EXTENDED_PERMS, or 0.
36 *
37 * if a valid AVC entry doesn't exist,this function returns -ENOENT.
38 * if kmalloc() called internal returns NULL, this function returns -ENOMEM.
39@@ -856,6 +857,23 @@ static int avc_update_node(struct selinu
40 struct hlist_head *head;
41 spinlock_t *lock;
42
43+ /*
44+ * If we are in a non-blocking code path, e.g. VFS RCU walk,
45+ * then we must not add permissions to a cache entry
46+ * because we cannot safely audit the denial. Otherwise,
47+ * during the subsequent blocking retry (e.g. VFS ref walk), we
48+ * will find the permissions already granted in the cache entry
49+ * and won't audit anything at all, leading to silent denials in
50+ * permissive mode that only appear when in enforcing mode.
51+ *
52+ * See the corresponding handling in slow_avc_audit(), and the
53+ * logic in selinux_inode_follow_link and selinux_inode_permission
54+ * for the VFS MAY_NOT_BLOCK flag, which is transliterated into
55+ * AVC_NONBLOCKING for avc_has_perm_noaudit().
56+ */
57+ if (flags & AVC_NONBLOCKING)
58+ return 0;
59+
60 node = avc_alloc_node(avc);
61 if (!node) {
62 rc = -ENOMEM;
63@@ -1115,7 +1133,7 @@ decision:
64 * @tsid: target security identifier
65 * @tclass: target security class
66 * @requested: requested permissions, interpreted based on @tclass
67- * @flags: AVC_STRICT or 0
68+ * @flags: AVC_STRICT, AVC_NONBLOCKING, or 0
69 * @avd: access vector decisions
70 *
71 * Check the AVC to determine whether the @requested permissions are granted
72@@ -1199,7 +1217,8 @@ int avc_has_perm_flags(struct selinux_st
73 struct av_decision avd;
74 int rc, rc2;
75
76- rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, requested, 0,
77+ rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, requested,
78+ (flags & MAY_NOT_BLOCK) ? AVC_NONBLOCKING : 0,
79 &avd);
80
81 rc2 = avc_audit(state, ssid, tsid, tclass, requested, &avd, rc,
82--- a/security/selinux/hooks.c
83+++ b/security/selinux/hooks.c
84@@ -3199,7 +3199,9 @@ static int selinux_inode_permission(stru
85 return PTR_ERR(isec);
86
87 rc = avc_has_perm_noaudit(&selinux_state,
88- sid, isec->sid, isec->sclass, perms, 0, &avd);
89+ sid, isec->sid, isec->sclass, perms,
90+ (flags & MAY_NOT_BLOCK) ? AVC_NONBLOCKING : 0,
91+ &avd);
92 audited = avc_audit_required(perms, &avd, rc,
93 from_access ? FILE__AUDIT_ACCESS : 0,
94 &denied);
95--- a/security/selinux/include/avc.h
96+++ b/security/selinux/include/avc.h
97@@ -142,6 +142,7 @@ static inline int avc_audit(struct selin
98
99 #define AVC_STRICT 1 /* Ignore permissive mode. */
100 #define AVC_EXTENDED_PERMS 2 /* update extended permissions */
101+#define AVC_NONBLOCKING 4 /* non blocking */
102 int avc_has_perm_noaudit(struct selinux_state *state,
103 u32 ssid, u32 tsid,
104 u16 tclass, u32 requested,