| From 1a37079c236d55fb31ebbf4b59945dab8ec8764c Mon Sep 17 00:00:00 2001 |
| From: Stephen Smalley <sds@tycho.nsa.gov> |
| Date: Fri, 22 Nov 2019 12:22:44 -0500 |
| Subject: selinux: revert "stop passing MAY_NOT_BLOCK to the AVC upon follow_link" |
| |
| From: Stephen Smalley <sds@tycho.nsa.gov> |
| |
| commit 1a37079c236d55fb31ebbf4b59945dab8ec8764c upstream. |
| |
| This reverts commit e46e01eebbbc ("selinux: stop passing MAY_NOT_BLOCK |
| to the AVC upon follow_link"). The correct fix is to instead fall |
| back to ref-walk if audit is required irrespective of the specific |
| audit data type. This is done in the next commit. |
| |
| Fixes: e46e01eebbbc ("selinux: stop passing MAY_NOT_BLOCK to the AVC upon follow_link") |
| Reported-by: Will Deacon <will@kernel.org> |
| Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov> |
| Signed-off-by: Paul Moore <paul@paul-moore.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| security/selinux/avc.c | 24 ++++++++++++++++++++++-- |
| security/selinux/hooks.c | 5 +++-- |
| security/selinux/include/avc.h | 5 +++++ |
| 3 files changed, 30 insertions(+), 4 deletions(-) |
| |
| --- a/security/selinux/avc.c |
| +++ b/security/selinux/avc.c |
| @@ -862,8 +862,9 @@ static int avc_update_node(struct selinu |
| * permissive mode that only appear when in enforcing mode. |
| * |
| * See the corresponding handling in slow_avc_audit(), and the |
| - * logic in selinux_inode_permission for the MAY_NOT_BLOCK flag, |
| - * which is transliterated into AVC_NONBLOCKING. |
| + * logic in selinux_inode_follow_link and selinux_inode_permission |
| + * for the VFS MAY_NOT_BLOCK flag, which is transliterated into |
| + * AVC_NONBLOCKING for avc_has_perm_noaudit(). |
| */ |
| if (flags & AVC_NONBLOCKING) |
| return 0; |
| @@ -1203,6 +1204,25 @@ int avc_has_perm(struct selinux_state *s |
| if (rc2) |
| return rc2; |
| return rc; |
| +} |
| + |
| +int avc_has_perm_flags(struct selinux_state *state, |
| + u32 ssid, u32 tsid, u16 tclass, u32 requested, |
| + struct common_audit_data *auditdata, |
| + int flags) |
| +{ |
| + struct av_decision avd; |
| + int rc, rc2; |
| + |
| + rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, requested, |
| + (flags & MAY_NOT_BLOCK) ? AVC_NONBLOCKING : 0, |
| + &avd); |
| + |
| + rc2 = avc_audit(state, ssid, tsid, tclass, requested, &avd, rc, |
| + auditdata, flags); |
| + if (rc2) |
| + return rc2; |
| + return rc; |
| } |
| |
| u32 avc_policy_seqno(struct selinux_state *state) |
| --- a/security/selinux/hooks.c |
| +++ b/security/selinux/hooks.c |
| @@ -3004,8 +3004,9 @@ static int selinux_inode_follow_link(str |
| if (IS_ERR(isec)) |
| return PTR_ERR(isec); |
| |
| - return avc_has_perm(&selinux_state, |
| - sid, isec->sid, isec->sclass, FILE__READ, &ad); |
| + return avc_has_perm_flags(&selinux_state, |
| + sid, isec->sid, isec->sclass, FILE__READ, &ad, |
| + rcu ? MAY_NOT_BLOCK : 0); |
| } |
| |
| static noinline int audit_inode_permission(struct inode *inode, |
| --- a/security/selinux/include/avc.h |
| +++ b/security/selinux/include/avc.h |
| @@ -153,6 +153,11 @@ int avc_has_perm(struct selinux_state *s |
| u32 ssid, u32 tsid, |
| u16 tclass, u32 requested, |
| struct common_audit_data *auditdata); |
| +int avc_has_perm_flags(struct selinux_state *state, |
| + u32 ssid, u32 tsid, |
| + u16 tclass, u32 requested, |
| + struct common_audit_data *auditdata, |
| + int flags); |
| |
| int avc_has_extended_perms(struct selinux_state *state, |
| u32 ssid, u32 tsid, u16 tclass, u32 requested, |