fs: Avoid premature clearing of capabilities (CVE-2015-1350)

Closes: #770492
This commit is contained in:
Salvatore Bonaccorso 2016-11-13 09:56:16 +01:00
parent b048cc5a7c
commit b7117071e0
3 changed files with 77 additions and 0 deletions

2
debian/changelog vendored
View File

@ -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

View File

@ -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

View File

@ -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