fs: Avoid premature clearing of capabilities (CVE-2015-1350)
Closes: #770492
This commit is contained in:
parent
b048cc5a7c
commit
b7117071e0
|
@ -47,6 +47,8 @@ linux (4.8.8-1) UNRELEASED; urgency=medium
|
|||
* ceph: Propagate dentry down to inode_change_ok()
|
||||
* fuse: Propagate dentry down to inode_change_ok()
|
||||
* fs: Give dentry to inode_change_ok() instead of inode
|
||||
* fs: Avoid premature clearing of capabilities (CVE-2015-1350)
|
||||
(Closes: #770492)
|
||||
|
||||
-- Salvatore Bonaccorso <carnil@debian.org> Tue, 15 Nov 2016 22:01:08 +0100
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
From: Jan Kara <jack@suse.cz>
|
||||
Date: Thu, 26 May 2016 17:21:32 +0200
|
||||
Subject: fs: Avoid premature clearing of capabilities
|
||||
Origin: https://git.kernel.org/linus/030b533c4fd4d2ec3402363323de4bb2983c9cee
|
||||
Debian-Bug: https://bugs.debian.org/770492
|
||||
|
||||
Currently, notify_change() clears capabilities or IMA attributes by
|
||||
calling security_inode_killpriv() before calling into ->setattr. Thus it
|
||||
happens before any other permission checks in inode_change_ok() and user
|
||||
is thus allowed to trigger clearing of capabilities or IMA attributes
|
||||
for any file he can look up e.g. by calling chown for that file. This is
|
||||
unexpected and can lead to user DoSing a system.
|
||||
|
||||
Fix the problem by calling security_inode_killpriv() at the end of
|
||||
inode_change_ok() instead of from notify_change(). At that moment we are
|
||||
sure user has permissions to do the requested change.
|
||||
|
||||
References: CVE-2015-1350
|
||||
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||
Signed-off-by: Jan Kara <jack@suse.cz>
|
||||
---
|
||||
fs/attr.c | 20 ++++++++++++++------
|
||||
1 file changed, 14 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/fs/attr.c b/fs/attr.c
|
||||
index 5c45909..83c8430 100644
|
||||
--- a/fs/attr.c
|
||||
+++ b/fs/attr.c
|
||||
@@ -47,7 +47,7 @@ int setattr_prepare(struct dentry *dentry, struct iattr *attr)
|
||||
|
||||
/* If force is set do it anyway. */
|
||||
if (ia_valid & ATTR_FORCE)
|
||||
- return 0;
|
||||
+ goto kill_priv;
|
||||
|
||||
/* Make sure a caller can chown. */
|
||||
if ((ia_valid & ATTR_UID) &&
|
||||
@@ -80,6 +80,16 @@ int setattr_prepare(struct dentry *dentry, struct iattr *attr)
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
+kill_priv:
|
||||
+ /* User has permission for the change */
|
||||
+ if (ia_valid & ATTR_KILL_PRIV) {
|
||||
+ int error;
|
||||
+
|
||||
+ error = security_inode_killpriv(dentry);
|
||||
+ if (error)
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(setattr_prepare);
|
||||
@@ -220,13 +230,11 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
|
||||
if (!(ia_valid & ATTR_MTIME_SET))
|
||||
attr->ia_mtime = now;
|
||||
if (ia_valid & ATTR_KILL_PRIV) {
|
||||
- attr->ia_valid &= ~ATTR_KILL_PRIV;
|
||||
- ia_valid &= ~ATTR_KILL_PRIV;
|
||||
error = security_inode_need_killpriv(dentry);
|
||||
- if (error > 0)
|
||||
- error = security_inode_killpriv(dentry);
|
||||
- if (error)
|
||||
+ if (error < 0)
|
||||
return error;
|
||||
+ if (error == 0)
|
||||
+ ia_valid = attr->ia_valid &= ~ATTR_KILL_PRIV;
|
||||
}
|
||||
|
||||
/*
|
||||
--
|
||||
2.10.2
|
||||
|
|
@ -97,6 +97,7 @@ bugfix/all/xfs-Propagate-dentry-down-to-inode_change_ok.patch
|
|||
bugfix/all/ceph-Propagate-dentry-down-to-inode_change_ok.patch
|
||||
bugfix/all/fuse-Propagate-dentry-down-to-inode_change_ok.patch
|
||||
bugfix/all/fs-Give-dentry-to-inode_change_ok-instead-of-inode.patch
|
||||
bugfix/all/fs-Avoid-premature-clearing-of-capabilities.patch
|
||||
|
||||
# ABI maintenance
|
||||
|
||||
|
|
Loading…
Reference in New Issue