diff options
author | Andy Lutomirski <luto@amacapital.net> | 2014-06-10 15:45:42 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-10 16:57:22 -0400 |
commit | 23adbe12ef7d3d4195e80800ab36b37bee28cd03 (patch) | |
tree | 000f8f8b3172aa6629b7c9a4148a96549a07acb6 /fs/attr.c | |
parent | 5b174fd6472b1d6b6402b30210a212f3fd770d96 (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/attr.c')
-rw-r--r-- | fs/attr.c | 8 |
1 files changed, 4 insertions, 4 deletions
@@ -50,14 +50,14 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr) | |||
50 | if ((ia_valid & ATTR_UID) && | 50 | if ((ia_valid & ATTR_UID) && |
51 | (!uid_eq(current_fsuid(), inode->i_uid) || | 51 | (!uid_eq(current_fsuid(), inode->i_uid) || |
52 | !uid_eq(attr->ia_uid, inode->i_uid)) && | 52 | !uid_eq(attr->ia_uid, inode->i_uid)) && |
53 | !inode_capable(inode, CAP_CHOWN)) | 53 | !capable_wrt_inode_uidgid(inode, CAP_CHOWN)) |
54 | return -EPERM; | 54 | return -EPERM; |
55 | 55 | ||
56 | /* Make sure caller can chgrp. */ | 56 | /* Make sure caller can chgrp. */ |
57 | if ((ia_valid & ATTR_GID) && | 57 | if ((ia_valid & ATTR_GID) && |
58 | (!uid_eq(current_fsuid(), inode->i_uid) || | 58 | (!uid_eq(current_fsuid(), inode->i_uid) || |
59 | (!in_group_p(attr->ia_gid) && !gid_eq(attr->ia_gid, inode->i_gid))) && | 59 | (!in_group_p(attr->ia_gid) && !gid_eq(attr->ia_gid, inode->i_gid))) && |
60 | !inode_capable(inode, CAP_CHOWN)) | 60 | !capable_wrt_inode_uidgid(inode, CAP_CHOWN)) |
61 | return -EPERM; | 61 | return -EPERM; |
62 | 62 | ||
63 | /* Make sure a caller can chmod. */ | 63 | /* Make sure a caller can chmod. */ |
@@ -67,7 +67,7 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr) | |||
67 | /* Also check the setgid bit! */ | 67 | /* Also check the setgid bit! */ |
68 | if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid : | 68 | if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid : |
69 | inode->i_gid) && | 69 | inode->i_gid) && |
70 | !inode_capable(inode, CAP_FSETID)) | 70 | !capable_wrt_inode_uidgid(inode, CAP_FSETID)) |
71 | attr->ia_mode &= ~S_ISGID; | 71 | attr->ia_mode &= ~S_ISGID; |
72 | } | 72 | } |
73 | 73 | ||
@@ -160,7 +160,7 @@ void setattr_copy(struct inode *inode, const struct iattr *attr) | |||
160 | umode_t mode = attr->ia_mode; | 160 | umode_t mode = attr->ia_mode; |
161 | 161 | ||
162 | if (!in_group_p(inode->i_gid) && | 162 | if (!in_group_p(inode->i_gid) && |
163 | !inode_capable(inode, CAP_FSETID)) | 163 | !capable_wrt_inode_uidgid(inode, CAP_FSETID)) |
164 | mode &= ~S_ISGID; | 164 | mode &= ~S_ISGID; |
165 | inode->i_mode = mode; | 165 | inode->i_mode = mode; |
166 | } | 166 | } |