Commit e795b71799ff0b27365020c9ddaa25d0d83f99c8

Authored by Serge E. Hallyn
Committed by Linus Torvalds
1 parent b0e77598f8

userns: userns: check user namespace for task->file uid equivalence checks

Cheat for now and say all files belong to init_user_ns.  Next step will be
to let superblocks belong to a user_ns, and derive inode_userns(inode)
from inode->i_sb->s_user_ns.  Finally we'll introduce more flexible
arrangements.

Changelog:
	Feb 15: make is_owner_or_cap take const struct inode
	Feb 23: make is_owner_or_cap bool

[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Serge E. Hallyn <serge.hallyn@canonical.com>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
Acked-by: Daniel Lezcano <daniel.lezcano@free.fr>
Acked-by: David Howells <dhowells@redhat.com>
Cc: James Morris <jmorris@namei.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 3 changed files with 40 additions and 7 deletions Side-by-side Diff

... ... @@ -25,6 +25,7 @@
25 25 #include <linux/async.h>
26 26 #include <linux/posix_acl.h>
27 27 #include <linux/ima.h>
  28 +#include <linux/cred.h>
28 29  
29 30 /*
30 31 * This is needed for the following functions:
... ... @@ -1733,4 +1734,20 @@
1733 1734 inode->i_mode = mode;
1734 1735 }
1735 1736 EXPORT_SYMBOL(inode_init_owner);
  1737 +
  1738 +/*
  1739 + * return true if current either has CAP_FOWNER to the
  1740 + * file, or owns the file.
  1741 + */
  1742 +bool is_owner_or_cap(const struct inode *inode)
  1743 +{
  1744 + struct user_namespace *ns = inode_userns(inode);
  1745 +
  1746 + if (current_user_ns() == ns && current_fsuid() == inode->i_uid)
  1747 + return true;
  1748 + if (ns_capable(ns, CAP_FOWNER))
  1749 + return true;
  1750 + return false;
  1751 +}
  1752 +EXPORT_SYMBOL(is_owner_or_cap);
... ... @@ -183,6 +183,9 @@
183 183  
184 184 mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
185 185  
  186 + if (current_user_ns() != inode_userns(inode))
  187 + goto other_perms;
  188 +
186 189 if (current_fsuid() == inode->i_uid)
187 190 mode >>= 6;
188 191 else {
... ... @@ -196,6 +199,7 @@
196 199 mode >>= 3;
197 200 }
198 201  
  202 +other_perms:
199 203 /*
200 204 * If the DACs are ok we don't need any capability check.
201 205 */
... ... @@ -237,7 +241,7 @@
237 241 * Executable DACs are overridable if at least one exec bit is set.
238 242 */
239 243 if (!(mask & MAY_EXEC) || execute_ok(inode))
240   - if (capable(CAP_DAC_OVERRIDE))
  244 + if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE))
241 245 return 0;
242 246  
243 247 /*
... ... @@ -245,7 +249,7 @@
245 249 */
246 250 mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
247 251 if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))
248   - if (capable(CAP_DAC_READ_SEARCH))
  252 + if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH))
249 253 return 0;
250 254  
251 255 return -EACCES;
... ... @@ -654,6 +658,7 @@
654 658 static inline int exec_permission(struct inode *inode, unsigned int flags)
655 659 {
656 660 int ret;
  661 + struct user_namespace *ns = inode_userns(inode);
657 662  
658 663 if (inode->i_op->permission) {
659 664 ret = inode->i_op->permission(inode, MAY_EXEC, flags);
... ... @@ -666,7 +671,8 @@
666 671 if (ret == -ECHILD)
667 672 return ret;
668 673  
669   - if (capable(CAP_DAC_OVERRIDE) || capable(CAP_DAC_READ_SEARCH))
  674 + if (ns_capable(ns, CAP_DAC_OVERRIDE) ||
  675 + ns_capable(ns, CAP_DAC_READ_SEARCH))
670 676 goto ok;
671 677  
672 678 return ret;
673 679  
... ... @@ -1842,11 +1848,15 @@
1842 1848  
1843 1849 if (!(dir->i_mode & S_ISVTX))
1844 1850 return 0;
  1851 + if (current_user_ns() != inode_userns(inode))
  1852 + goto other_userns;
1845 1853 if (inode->i_uid == fsuid)
1846 1854 return 0;
1847 1855 if (dir->i_uid == fsuid)
1848 1856 return 0;
1849   - return !capable(CAP_FOWNER);
  1857 +
  1858 +other_userns:
  1859 + return !ns_capable(inode_userns(inode), CAP_FOWNER);
1850 1860 }
1851 1861  
1852 1862 /*
... ... @@ -2440,7 +2450,8 @@
2440 2450 if (error)
2441 2451 return error;
2442 2452  
2443   - if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD))
  2453 + if ((S_ISCHR(mode) || S_ISBLK(mode)) &&
  2454 + !ns_capable(inode_userns(dir), CAP_MKNOD))
2444 2455 return -EPERM;
2445 2456  
2446 2457 if (!dir->i_op->mknod)
... ... @@ -1457,8 +1457,13 @@
1457 1457 #define put_fs_excl() atomic_dec(&current->fs_excl)
1458 1458 #define has_fs_excl() atomic_read(&current->fs_excl)
1459 1459  
1460   -#define is_owner_or_cap(inode) \
1461   - ((current_fsuid() == (inode)->i_uid) || capable(CAP_FOWNER))
  1460 +/*
  1461 + * until VFS tracks user namespaces for inodes, just make all files
  1462 + * belong to init_user_ns
  1463 + */
  1464 +extern struct user_namespace init_user_ns;
  1465 +#define inode_userns(inode) (&init_user_ns)
  1466 +extern bool is_owner_or_cap(const struct inode *inode);
1462 1467  
1463 1468 /* not quite ready to be deprecated, but... */
1464 1469 extern void lock_super(struct super_block *);