aboutsummaryrefslogtreecommitdiffstats
path: root/fs/inode.c
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@amacapital.net>2014-06-10 15:45:42 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-10 16:57:22 -0400
commit23adbe12ef7d3d4195e80800ab36b37bee28cd03 (patch)
tree000f8f8b3172aa6629b7c9a4148a96549a07acb6 /fs/inode.c
parent5b174fd6472b1d6b6402b30210a212f3fd770d96 (diff)
fs,userns: Change inode_capable to capable_wrt_inode_uidgid
The kernel has no concept of capabilities with respect to inodes; inodes exist independently of namespaces. For example, inode_capable(inode, CAP_LINUX_IMMUTABLE) would be nonsense. This patch changes inode_capable to check for uid and gid mappings and renames it to capable_wrt_inode_uidgid, which should make it more obvious what it does. Fixes CVE-2014-4014. Cc: Theodore Ts'o <tytso@mit.edu> Cc: Serge Hallyn <serge.hallyn@ubuntu.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Dave Chinner <david@fromorbit.com> Cc: stable@vger.kernel.org Signed-off-by: Andy Lutomirski <luto@amacapital.net> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/inode.c')
-rw-r--r--fs/inode.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/fs/inode.c b/fs/inode.c
index 2feb9b69f1be..6eecb7ff0b9a 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1839,14 +1839,18 @@ EXPORT_SYMBOL(inode_init_owner);
1839 * inode_owner_or_capable - check current task permissions to inode 1839 * inode_owner_or_capable - check current task permissions to inode
1840 * @inode: inode being checked 1840 * @inode: inode being checked
1841 * 1841 *
1842 * Return true if current either has CAP_FOWNER to the inode, or 1842 * Return true if current either has CAP_FOWNER in a namespace with the
1843 * owns the file. 1843 * inode owner uid mapped, or owns the file.
1844 */ 1844 */
1845bool inode_owner_or_capable(const struct inode *inode) 1845bool inode_owner_or_capable(const struct inode *inode)
1846{ 1846{
1847 struct user_namespace *ns;
1848
1847 if (uid_eq(current_fsuid(), inode->i_uid)) 1849 if (uid_eq(current_fsuid(), inode->i_uid))
1848 return true; 1850 return true;
1849 if (inode_capable(inode, CAP_FOWNER)) 1851
1852 ns = current_user_ns();
1853 if (ns_capable(ns, CAP_FOWNER) && kuid_has_mapping(ns, inode->i_uid))
1850 return true; 1854 return true;
1851 return false; 1855 return false;
1852} 1856}