diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2011-11-14 19:24:06 -0500 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2012-04-07 20:02:46 -0400 |
commit | 1a48e2ac034d47ed843081c4523b63c46b46888b (patch) | |
tree | d3a32ac7ffc47b075a64701a2fd74e00bbccf84d /fs/namei.c | |
parent | 973c5914260d75292f71a4729753086b9e863d57 (diff) |
userns: Replace the hard to write inode_userns with inode_capable.
This represents a change in strategy of how to handle user namespaces.
Instead of tagging everything explicitly with a user namespace and bulking
up all of the comparisons of uids and gids in the kernel, all uids and gids
in use will have a mapping to a flat kuid and kgid spaces respectively. This
allows much more of the existing logic to be preserved and in general
allows for faster code.
In this new and improved world we allow someone to utiliize capabilities
over an inode if the inodes owner mapps into the capabilities holders user
namespace and the user has capabilities in their user namespace. Which
is simple and efficient.
Moving the fs uid comparisons to be comparisons in a flat kuid space
follows in later patches, something that is only significant if you
are using user namespaces.
Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 18 |
1 files changed, 5 insertions, 13 deletions
diff --git a/fs/namei.c b/fs/namei.c index 701954d68ac7..941c4362e298 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -228,9 +228,6 @@ static int acl_permission_check(struct inode *inode, int mask) | |||
228 | { | 228 | { |
229 | unsigned int mode = inode->i_mode; | 229 | unsigned int mode = inode->i_mode; |
230 | 230 | ||
231 | if (current_user_ns() != inode_userns(inode)) | ||
232 | goto other_perms; | ||
233 | |||
234 | if (likely(current_fsuid() == inode->i_uid)) | 231 | if (likely(current_fsuid() == inode->i_uid)) |
235 | mode >>= 6; | 232 | mode >>= 6; |
236 | else { | 233 | else { |
@@ -244,7 +241,6 @@ static int acl_permission_check(struct inode *inode, int mask) | |||
244 | mode >>= 3; | 241 | mode >>= 3; |
245 | } | 242 | } |
246 | 243 | ||
247 | other_perms: | ||
248 | /* | 244 | /* |
249 | * If the DACs are ok we don't need any capability check. | 245 | * If the DACs are ok we don't need any capability check. |
250 | */ | 246 | */ |
@@ -280,10 +276,10 @@ int generic_permission(struct inode *inode, int mask) | |||
280 | 276 | ||
281 | if (S_ISDIR(inode->i_mode)) { | 277 | if (S_ISDIR(inode->i_mode)) { |
282 | /* DACs are overridable for directories */ | 278 | /* DACs are overridable for directories */ |
283 | if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE)) | 279 | if (inode_capable(inode, CAP_DAC_OVERRIDE)) |
284 | return 0; | 280 | return 0; |
285 | if (!(mask & MAY_WRITE)) | 281 | if (!(mask & MAY_WRITE)) |
286 | if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH)) | 282 | if (inode_capable(inode, CAP_DAC_READ_SEARCH)) |
287 | return 0; | 283 | return 0; |
288 | return -EACCES; | 284 | return -EACCES; |
289 | } | 285 | } |
@@ -293,7 +289,7 @@ int generic_permission(struct inode *inode, int mask) | |||
293 | * at least one exec bit set. | 289 | * at least one exec bit set. |
294 | */ | 290 | */ |
295 | if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO)) | 291 | if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO)) |
296 | if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE)) | 292 | if (inode_capable(inode, CAP_DAC_OVERRIDE)) |
297 | return 0; | 293 | return 0; |
298 | 294 | ||
299 | /* | 295 | /* |
@@ -301,7 +297,7 @@ int generic_permission(struct inode *inode, int mask) | |||
301 | */ | 297 | */ |
302 | mask &= MAY_READ | MAY_WRITE | MAY_EXEC; | 298 | mask &= MAY_READ | MAY_WRITE | MAY_EXEC; |
303 | if (mask == MAY_READ) | 299 | if (mask == MAY_READ) |
304 | if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH)) | 300 | if (inode_capable(inode, CAP_DAC_READ_SEARCH)) |
305 | return 0; | 301 | return 0; |
306 | 302 | ||
307 | return -EACCES; | 303 | return -EACCES; |
@@ -1964,15 +1960,11 @@ static inline int check_sticky(struct inode *dir, struct inode *inode) | |||
1964 | 1960 | ||
1965 | if (!(dir->i_mode & S_ISVTX)) | 1961 | if (!(dir->i_mode & S_ISVTX)) |
1966 | return 0; | 1962 | return 0; |
1967 | if (current_user_ns() != inode_userns(inode)) | ||
1968 | goto other_userns; | ||
1969 | if (inode->i_uid == fsuid) | 1963 | if (inode->i_uid == fsuid) |
1970 | return 0; | 1964 | return 0; |
1971 | if (dir->i_uid == fsuid) | 1965 | if (dir->i_uid == fsuid) |
1972 | return 0; | 1966 | return 0; |
1973 | 1967 | return !inode_capable(inode, CAP_FOWNER); | |
1974 | other_userns: | ||
1975 | return !ns_capable(inode_userns(inode), CAP_FOWNER); | ||
1976 | } | 1968 | } |
1977 | 1969 | ||
1978 | /* | 1970 | /* |