Skip to content

Commit

Permalink
fs: Avoid premature clearing of capabilities
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Jan Kara <[email protected]>
  • Loading branch information
jankara committed Sep 22, 2016
1 parent 31051c8 commit 030b533
Showing 1 changed file with 14 additions and 6 deletions.
20 changes: 14 additions & 6 deletions fs/attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) &&
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

/*
Expand Down

0 comments on commit 030b533

Please sign in to comment.