aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/inode.c6
-rw-r--r--fs/namei.c18
-rw-r--r--include/linux/capability.h2
-rw-r--r--include/linux/fs.h6
-rw-r--r--kernel/capability.c19
5 files changed, 28 insertions, 23 deletions
diff --git a/fs/inode.c b/fs/inode.c
index 9f4f5fecc096..f0c4ace408e4 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1732,11 +1732,9 @@ EXPORT_SYMBOL(inode_init_owner);
1732 */ 1732 */
1733bool inode_owner_or_capable(const struct inode *inode) 1733bool inode_owner_or_capable(const struct inode *inode)
1734{ 1734{
1735 struct user_namespace *ns = inode_userns(inode); 1735 if (current_fsuid() == inode->i_uid)
1736
1737 if (current_user_ns() == ns && current_fsuid() == inode->i_uid)
1738 return true; 1736 return true;
1739 if (ns_capable(ns, CAP_FOWNER)) 1737 if (inode_capable(inode, CAP_FOWNER))
1740 return true; 1738 return true;
1741 return false; 1739 return false;
1742} 1740}
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
247other_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);
1974other_userns:
1975 return !ns_capable(inode_userns(inode), CAP_FOWNER);
1976} 1968}
1977 1969
1978/* 1970/*
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 12d52dedb229..a76eca907470 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -374,6 +374,7 @@ struct cpu_vfs_cap_data {
374 374
375#ifdef __KERNEL__ 375#ifdef __KERNEL__
376 376
377struct inode;
377struct dentry; 378struct dentry;
378struct user_namespace; 379struct user_namespace;
379 380
@@ -548,6 +549,7 @@ extern bool has_ns_capability_noaudit(struct task_struct *t,
548extern bool capable(int cap); 549extern bool capable(int cap);
549extern bool ns_capable(struct user_namespace *ns, int cap); 550extern bool ns_capable(struct user_namespace *ns, int cap);
550extern bool nsown_capable(int cap); 551extern bool nsown_capable(int cap);
552extern bool inode_capable(const struct inode *inode, int cap);
551 553
552/* audit system wants to get cap info from files as well */ 554/* audit system wants to get cap info from files as well */
553extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps); 555extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 135693e79f2b..a6c5efbee0d7 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1522,12 +1522,6 @@ enum {
1522#define vfs_check_frozen(sb, level) \ 1522#define vfs_check_frozen(sb, level) \
1523 wait_event((sb)->s_wait_unfrozen, ((sb)->s_frozen < (level))) 1523 wait_event((sb)->s_wait_unfrozen, ((sb)->s_frozen < (level)))
1524 1524
1525/*
1526 * until VFS tracks user namespaces for inodes, just make all files
1527 * belong to init_user_ns
1528 */
1529extern struct user_namespace init_user_ns;
1530#define inode_userns(inode) (&init_user_ns)
1531extern bool inode_owner_or_capable(const struct inode *inode); 1525extern bool inode_owner_or_capable(const struct inode *inode);
1532 1526
1533/* not quite ready to be deprecated, but... */ 1527/* not quite ready to be deprecated, but... */
diff --git a/kernel/capability.c b/kernel/capability.c
index 3f1adb6c6470..cc5f0718215d 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -419,3 +419,22 @@ bool nsown_capable(int cap)
419{ 419{
420 return ns_capable(current_user_ns(), cap); 420 return ns_capable(current_user_ns(), cap);
421} 421}
422
423/**
424 * inode_capable - Check superior capability over inode
425 * @inode: The inode in question
426 * @cap: The capability in question
427 *
428 * Return true if the current task has the given superior capability
429 * targeted at it's own user namespace and that the given inode is owned
430 * by the current user namespace or a child namespace.
431 *
432 * Currently inodes can only be owned by the initial user namespace.
433 *
434 */
435bool inode_capable(const struct inode *inode, int cap)
436{
437 struct user_namespace *ns = current_user_ns();
438
439 return ns_capable(ns, cap) && (ns == &init_user_ns);
440}