diff options
author | Stephen Smalley <sds@tycho.nsa.gov> | 2019-11-22 12:22:45 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-02-14 16:34:20 -0500 |
commit | 2d8fdc5744ff678e23d8869f57cedab4f5546f74 (patch) | |
tree | b369d3b79f29831b600663990272e1c4269df559 /security/selinux/hooks.c | |
parent | ae7f404d922747e9e97679d5bbde51e0a72693ca (diff) |
selinux: fall back to ref-walk if audit is required
commit 0188d5c025ca8fe756ba3193bd7d150139af5a88 upstream.
commit bda0be7ad994 ("security: make inode_follow_link RCU-walk aware")
passed down the rcu flag to the SELinux AVC, but failed to adjust the
test in slow_avc_audit() to also return -ECHILD on LSM_AUDIT_DATA_DENTRY.
Previously, we only returned -ECHILD if generating an audit record with
LSM_AUDIT_DATA_INODE since this was only relevant from inode_permission.
Move the handling of MAY_NOT_BLOCK to avc_audit() and its inlined
equivalent in selinux_inode_permission() immediately after we determine
that audit is required, and always fall back to ref-walk in this case.
Fixes: bda0be7ad994 ("security: make inode_follow_link RCU-walk aware")
Reported-by: Will Deacon <will@kernel.org>
Suggested-by: Al Viro <viro@zeniv.linux.org.uk>
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>
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 0426ce3c19e9..39410913a694 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3023,8 +3023,7 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode, static noinline int audit_inode_permission(struct inode *inode, u32 perms, u32 audited, u32 denied, - int result, - unsigned flags) + int result) { struct common_audit_data ad; struct inode_security_struct *isec = selinux_inode(inode); @@ -3035,7 +3034,7 @@ static noinline int audit_inode_permission(struct inode *inode, rc = slow_avc_audit(&selinux_state, current_sid(), isec->sid, isec->sclass, perms, - audited, denied, result, &ad, flags); + audited, denied, result, &ad); if (rc) return rc; return 0; @@ -3082,7 +3081,11 @@ static int selinux_inode_permission(struct inode *inode, int mask) if (likely(!audited)) return rc; - rc2 = audit_inode_permission(inode, perms, audited, denied, rc, flags); + /* fall back to ref-walk if we have to generate audit */ + if (flags & MAY_NOT_BLOCK) + return -ECHILD; + + rc2 = audit_inode_permission(inode, perms, audited, denied, rc); if (rc2) return rc2; return rc; |