History

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace

Pull namespace changes from Eric Biederman: "This is an assorted mishmash of small cleanups, enhancements and bug fixes. The major theme is user namespace mount restrictions. nsown_capable is killed as it encourages not thinking about details that need to be considered. A very hard to hit pid namespace exiting bug was finally tracked and fixed. A couple of cleanups to the basic namespace infrastructure. Finally there is an enhancement that makes per user namespace capabilities usable as capabilities, and an enhancement that allows the per userns root to nice other processes in the user namespace" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: userns: Kill nsown_capable it makes the wrong thing easy capabilities: allow nice if we are privileged pidns: Don't have unshare(CLONE_NEWPID) imply CLONE_THREAD userns: Allow PR_CAPBSET_DROP in a user namespace. namespaces: Simplify copy_namespaces so it is clear what is going on. pidns: Fix hang in zap_pid_ns_processes by sending a potentially extra wakeup sysfs: Restrict mounting sysfs userns: Better restrictions on when proc and sysfs can be mounted vfs: Don't copy mount bind mounts of /proc/<pid>/ns/mnt between namespaces kernel/nsproxy.c: Improving a snippet of code. proc: Restrict mounting the proc filesystem vfs: Lock in place mounts from more privileged users

Linus Torvalds committed 13 years ago

Commit c7c45912 parents 11c7b03 c7b96ac27 files · +177 −104Browse files

Unified · Split

27 files
  1. fs/namespace.c +95 −26
  2. fs/open.c +1 −1
  3. fs/pnode.h +4 −1
  4. fs/proc/root.c +5 −1
  5. fs/sysfs/mount.c +9 −2
  6. include/linux/capability.h +0 −1
  7. include/linux/fs.h +1 −0
  8. include/linux/kobject_ns.h +2 −0
  9. include/linux/mount.h +1 −0
  10. include/linux/user_namespace.h +0 −4
  11. ipc/namespace.c +1 −1
  12. kernel/capability.c +0 −12
  13. kernel/fork.c +0 −5
  14. kernel/groups.c +1 −1
  15. kernel/nsproxy.c +12 −24
  16. kernel/pid.c +1 −0
  17. kernel/pid_namespace.c +1 −1
  18. kernel/sys.c +10 −10
  19. kernel/uid16.c +1 −1
  20. kernel/user.c +0 −2
  21. kernel/user_namespace.c +0 −2
  22. kernel/utsname.c +1 −1
  23. lib/kobject.c +15 −0
  24. net/core/net-sysfs.c +8 −0
  25. net/core/net_namespace.c +1 −1
  26. net/core/scm.c +2 −2
  27. security/commoncap.c +5 −5
fs/namespace.c+95−26
@@ -831,6 +831,10 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, · 830 unmodified lines
831 if ((flag & CL_UNPRIVILEGED) && (mnt->mnt.mnt_flags & MNT_READONLY))831 if ((flag & CL_UNPRIVILEGED) && (mnt->mnt.mnt_flags & MNT_READONLY))
832 mnt->mnt.mnt_flags |= MNT_LOCK_READONLY;832 mnt->mnt.mnt_flags |= MNT_LOCK_READONLY;
833 833
834 /* Don't allow unprivileged users to reveal what is under a mount */
835 if ((flag & CL_UNPRIVILEGED) && list_empty(&old->mnt_expire))
836 mnt->mnt.mnt_flags |= MNT_LOCKED;
837
834 atomic_inc(&sb->s_active);838 atomic_inc(&sb->s_active);
835 mnt->mnt.mnt_sb = sb;839 mnt->mnt.mnt_sb = sb;
836 mnt->mnt.mnt_root = dget(root);840 mnt->mnt.mnt_root = dget(root);
@@ -1327,6 +1331,8 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags) · 490 unmodified lines
1327 goto dput_and_out;1331 goto dput_and_out;
1328 if (!check_mnt(mnt))1332 if (!check_mnt(mnt))
1329 goto dput_and_out;1333 goto dput_and_out;
1334 if (mnt->mnt.mnt_flags & MNT_LOCKED)
1335 goto dput_and_out;
1330 1336
1331 retval = do_umount(mnt, flags);1337 retval = do_umount(mnt, flags);
1332dput_and_out:1338dput_and_out:
@@ -1349,14 +1355,11 @@ SYSCALL_DEFINE1(oldumount, char __user *, name) · 16 unmodified lines
1349 1355
1350#endif1356#endif
1351 1357
1352static bool mnt_ns_loop(struct path *path)1358static bool is_mnt_ns_file(struct dentry *dentry)
1353{1359{
1354 /* Could bind mounting the mount namespace inode cause a1360 /* Is this a proxy for a mount namespace? */
1355 * mount namespace loop?1361 struct inode *inode = dentry->d_inode;
1356 */
1357 struct inode *inode = path->dentry->d_inode;
1358 struct proc_ns *ei;1362 struct proc_ns *ei;
1359 struct mnt_namespace *mnt_ns;
1360 1363
1361 if (!proc_ns_inode(inode))1364 if (!proc_ns_inode(inode))
1362 return false;1365 return false;
@@ -1365,7 +1368,19 @@ static bool mnt_ns_loop(struct path *path) · 2 unmodified lines
1365 if (ei->ns_ops != &mntns_operations)1368 if (ei->ns_ops != &mntns_operations)
1366 return false;1369 return false;
1367 1370
1368 mnt_ns = ei->ns;1371 return true;
1372}
1373
1374static bool mnt_ns_loop(struct dentry *dentry)
1375{
1376 /* Could bind mounting the mount namespace inode cause a
1377 * mount namespace loop?
1378 */
1379 struct mnt_namespace *mnt_ns;
1380 if (!is_mnt_ns_file(dentry))
1381 return false;
1382
1383 mnt_ns = get_proc_ns(dentry->d_inode)->ns;
1369 return current->nsproxy->mnt_ns->seq >= mnt_ns->seq;1384 return current->nsproxy->mnt_ns->seq >= mnt_ns->seq;
1370}1385}
1371 1386
@@ -1374,13 +1389,17 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, · 2 unmodified lines
1374{1389{
1375 struct mount *res, *p, *q, *r, *parent;1390 struct mount *res, *p, *q, *r, *parent;
1376 1391
1377 if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt))1392 if (!(flag & CL_COPY_UNBINDABLE) && IS_MNT_UNBINDABLE(mnt))
1393 return ERR_PTR(-EINVAL);
1394
1395 if (!(flag & CL_COPY_MNT_NS_FILE) && is_mnt_ns_file(dentry))
1378 return ERR_PTR(-EINVAL);1396 return ERR_PTR(-EINVAL);
1379 1397
1380 res = q = clone_mnt(mnt, dentry, flag);1398 res = q = clone_mnt(mnt, dentry, flag);
1381 if (IS_ERR(q))1399 if (IS_ERR(q))
1382 return q;1400 return q;
1383 1401
1402 q->mnt.mnt_flags &= ~MNT_LOCKED;
1384 q->mnt_mountpoint = mnt->mnt_mountpoint;1403 q->mnt_mountpoint = mnt->mnt_mountpoint;
1385 1404
1386 p = mnt;1405 p = mnt;
@@ -1390,7 +1409,13 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, · 3 unmodified lines
1390 continue;1409 continue;
1391 1410
1392 for (s = r; s; s = next_mnt(s, r)) {1411 for (s = r; s; s = next_mnt(s, r)) {
1393 if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(s)) {1412 if (!(flag & CL_COPY_UNBINDABLE) &&
1413 IS_MNT_UNBINDABLE(s)) {
1414 s = skip_mnt_tree(s);
1415 continue;
1416 }
1417 if (!(flag & CL_COPY_MNT_NS_FILE) &&
1418 is_mnt_ns_file(s->mnt.mnt_root)) {
1394 s = skip_mnt_tree(s);1419 s = skip_mnt_tree(s);
1395 continue;1420 continue;
1396 }1421 }
@@ -1696,6 +1721,19 @@ static int do_change_type(struct path *path, int flag) · 299 unmodified lines
1696 return err;1721 return err;
1697}1722}
1698 1723
1724static bool has_locked_children(struct mount *mnt, struct dentry *dentry)
1725{
1726 struct mount *child;
1727 list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
1728 if (!is_subdir(child->mnt_mountpoint, dentry))
1729 continue;
1730
1731 if (child->mnt.mnt_flags & MNT_LOCKED)
1732 return true;
1733 }
1734 return false;
1735}
1736
1699/*1737/*
1700 * do loopback mount.1738 * do loopback mount.
1701 */1739 */
@@ -1713,7 +1751,7 @@ static int do_loopback(struct path *path, const char *old_name, · 11 unmodified lines
1713 return err;1751 return err;
1714 1752
1715 err = -EINVAL;1753 err = -EINVAL;
1716 if (mnt_ns_loop(&old_path))1754 if (mnt_ns_loop(old_path.dentry))
1717 goto out; 1755 goto out;
1718 1756
1719 mp = lock_mount(path);1757 mp = lock_mount(path);
@@ -1731,8 +1769,11 @@ static int do_loopback(struct path *path, const char *old_name, · 11 unmodified lines
1731 if (!check_mnt(parent) || !check_mnt(old))1769 if (!check_mnt(parent) || !check_mnt(old))
1732 goto out2;1770 goto out2;
1733 1771
1772 if (!recurse && has_locked_children(old, old_path.dentry))
1773 goto out2;
1774
1734 if (recurse)1775 if (recurse)
1735 mnt = copy_tree(old, old_path.dentry, 0);1776 mnt = copy_tree(old, old_path.dentry, CL_COPY_MNT_NS_FILE);
1736 else1777 else
1737 mnt = clone_mnt(old, old_path.dentry, 0);1778 mnt = clone_mnt(old, old_path.dentry, 0);
1738 1779
@@ -1741,6 +1782,8 @@ static int do_loopback(struct path *path, const char *old_name, · 2 unmodified lines
1741 goto out2;1782 goto out2;
1742 }1783 }
1743 1784
1785 mnt->mnt.mnt_flags &= ~MNT_LOCKED;
1786
1744 err = graft_tree(mnt, parent, mp);1787 err = graft_tree(mnt, parent, mp);
1745 if (err) {1788 if (err) {
1746 br_write_lock(&vfsmount_lock);1789 br_write_lock(&vfsmount_lock);
@@ -1853,6 +1896,9 @@ static int do_move_mount(struct path *path, const char *old_name) · 106 unmodified lines
1853 if (!check_mnt(p) || !check_mnt(old))1896 if (!check_mnt(p) || !check_mnt(old))
1854 goto out1;1897 goto out1;
1855 1898
1899 if (old->mnt.mnt_flags & MNT_LOCKED)
1900 goto out1;
1901
1856 err = -EINVAL;1902 err = -EINVAL;
1857 if (old_path.dentry != old_path.mnt->mnt_root)1903 if (old_path.dentry != old_path.mnt->mnt_root)
1858 goto out1;1904 goto out1;
@@ -2389,7 +2435,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, · 530 unmodified lines
2389 2435
2390 namespace_lock();2436 namespace_lock();
2391 /* First pass: copy the tree topology */2437 /* First pass: copy the tree topology */
2392 copy_flags = CL_COPY_ALL | CL_EXPIRE;2438 copy_flags = CL_COPY_UNBINDABLE | CL_EXPIRE;
2393 if (user_ns != mnt_ns->user_ns)2439 if (user_ns != mnt_ns->user_ns)
2394 copy_flags |= CL_SHARED_TO_SLAVE | CL_UNPRIVILEGED;2440 copy_flags |= CL_SHARED_TO_SLAVE | CL_UNPRIVILEGED;
2395 new = copy_tree(old, old->mnt.mnt_root, copy_flags);2441 new = copy_tree(old, old->mnt.mnt_root, copy_flags);
@@ -2424,6 +2470,10 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, · 28 unmodified lines
2424 }2470 }
2425 p = next_mnt(p, old);2471 p = next_mnt(p, old);
2426 q = next_mnt(q, new);2472 q = next_mnt(q, new);
2473 if (!q)
2474 break;
2475 while (p->mnt.mnt_root != q->mnt.mnt_root)
2476 p = next_mnt(p, old);
2427 }2477 }
2428 namespace_unlock();2478 namespace_unlock();
2429 2479
@@ -2630,6 +2680,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, · 200 unmodified lines
2630 goto out4;2680 goto out4;
2631 if (!check_mnt(root_mnt) || !check_mnt(new_mnt))2681 if (!check_mnt(root_mnt) || !check_mnt(new_mnt))
2632 goto out4;2682 goto out4;
2683 if (new_mnt->mnt.mnt_flags & MNT_LOCKED)
2684 goto out4;
2633 error = -ENOENT;2685 error = -ENOENT;
2634 if (d_unlinked(new.dentry))2686 if (d_unlinked(new.dentry))
2635 goto out4;2687 goto out4;
@@ -2653,6 +2705,10 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, · 17 unmodified lines
2653 br_write_lock(&vfsmount_lock);2705 br_write_lock(&vfsmount_lock);
2654 detach_mnt(new_mnt, &parent_path);2706 detach_mnt(new_mnt, &parent_path);
2655 detach_mnt(root_mnt, &root_parent);2707 detach_mnt(root_mnt, &root_parent);
2708 if (root_mnt->mnt.mnt_flags & MNT_LOCKED) {
2709 new_mnt->mnt.mnt_flags |= MNT_LOCKED;
2710 root_mnt->mnt.mnt_flags &= ~MNT_LOCKED;
2711 }
2656 /* mount old root on put_old */2712 /* mount old root on put_old */
2657 attach_mnt(root_mnt, old_mnt, old_mp);2713 attach_mnt(root_mnt, old_mnt, old_mp);
2658 /* mount new_root on / */2714 /* mount new_root on / */
@@ -2811,25 +2867,38 @@ bool current_chrooted(void) · 152 unmodified lines
2811 return chrooted;2867 return chrooted;
2812}2868}
2813 2869
2814void update_mnt_policy(struct user_namespace *userns)2870bool fs_fully_visible(struct file_system_type *type)
2815{2871{
2816 struct mnt_namespace *ns = current->nsproxy->mnt_ns;2872 struct mnt_namespace *ns = current->nsproxy->mnt_ns;
2817 struct mount *mnt;2873 struct mount *mnt;
2874 bool visible = false;
2818 2875
2819 down_read(&namespace_sem);2876 if (unlikely(!ns))
2877 return false;
2878
2879 namespace_lock();
2820 list_for_each_entry(mnt, &ns->list, mnt_list) {2880 list_for_each_entry(mnt, &ns->list, mnt_list) {
2821 switch (mnt->mnt.mnt_sb->s_magic) {2881 struct mount *child;
2822 case SYSFS_MAGIC:2882 if (mnt->mnt.mnt_sb->s_type != type)
2823 userns->may_mount_sysfs = true;2883 continue;
2824 break;2884
2825 case PROC_SUPER_MAGIC:2885 /* This mount is not fully visible if there are any child mounts
2826 userns->may_mount_proc = true;2886 * that cover anything except for empty directories.
2827 break;2887 */
2888 list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
2889 struct inode *inode = child->mnt_mountpoint->d_inode;
2890 if (!S_ISDIR(inode->i_mode))
2891 goto next;
2892 if (inode->i_nlink != 2)
2893 goto next;
2828 }2894 }
2829 if (userns->may_mount_sysfs && userns->may_mount_proc)2895 visible = true;
2830 break;2896 goto found;
2897 next: ;
2831 }2898 }
2832 up_read(&namespace_sem);2899found:
2900 namespace_unlock();
2901 return visible;
2833}2902}
2834 2903
2835static void *mntns_get(struct task_struct *task)2904static void *mntns_get(struct task_struct *task)
@@ -2860,8 +2929,8 @@ static int mntns_install(struct nsproxy *nsproxy, void *ns) · 24 unmodified lines
2860 struct path root;2929 struct path root;
2861 2930
2862 if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) ||2931 if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) ||
2863 !nsown_capable(CAP_SYS_CHROOT) ||2932 !ns_capable(current_user_ns(), CAP_SYS_CHROOT) ||
2864 !nsown_capable(CAP_SYS_ADMIN))2933 !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
2865 return -EPERM;2934 return -EPERM;
2866 2935
2867 if (fs->users != 1)2936 if (fs->users != 1)
fs/open.c+1−1
@@ -443,7 +443,7 @@ retry: · 442 unmodified lines
443 goto dput_and_out;443 goto dput_and_out;
444 444
445 error = -EPERM;445 error = -EPERM;
446 if (!nsown_capable(CAP_SYS_CHROOT))446 if (!ns_capable(current_user_ns(), CAP_SYS_CHROOT))
447 goto dput_and_out;447 goto dput_and_out;
448 error = security_path_chroot(&path);448 error = security_path_chroot(&path);
449 if (error)449 if (error)
fs/pnode.h+4−1
@@ -19,11 +19,14 @@ · 18 unmodified lines
19 19
20#define CL_EXPIRE 0x0120#define CL_EXPIRE 0x01
21#define CL_SLAVE 0x0221#define CL_SLAVE 0x02
22#define CL_COPY_ALL 0x0422#define CL_COPY_UNBINDABLE 0x04
23#define CL_MAKE_SHARED 0x0823#define CL_MAKE_SHARED 0x08
24#define CL_PRIVATE 0x1024#define CL_PRIVATE 0x10
25#define CL_SHARED_TO_SLAVE 0x2025#define CL_SHARED_TO_SLAVE 0x20
26#define CL_UNPRIVILEGED 0x4026#define CL_UNPRIVILEGED 0x40
27#define CL_COPY_MNT_NS_FILE 0x80
28
29#define CL_COPY_ALL (CL_COPY_UNBINDABLE | CL_COPY_MNT_NS_FILE)
27 30
28static inline void set_mnt_shared(struct mount *mnt)31static inline void set_mnt_shared(struct mount *mnt)
29{32{
fs/proc/root.c+5−1
@@ -110,7 +110,11 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, · 109 unmodified lines
110 ns = task_active_pid_ns(current);110 ns = task_active_pid_ns(current);
111 options = data;111 options = data;
112 112
113 if (!current_user_ns()->may_mount_proc)113 if (!capable(CAP_SYS_ADMIN) && !fs_fully_visible(fs_type))
114 return ERR_PTR(-EPERM);
115
116 /* Does the mounter have privilege over the pid namespace? */
117 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN))
114 return ERR_PTR(-EPERM);118 return ERR_PTR(-EPERM);
115 }119 }
116 120
fs/sysfs/mount.c+9−2
@@ -112,8 +112,15 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type, · 111 unmodified lines
112 struct super_block *sb;112 struct super_block *sb;
113 int error;113 int error;
114 114
115 if (!(flags & MS_KERNMOUNT) && !current_user_ns()->may_mount_sysfs)115 if (!(flags & MS_KERNMOUNT)) {
116 return ERR_PTR(-EPERM);116 if (!capable(CAP_SYS_ADMIN) && !fs_fully_visible(fs_type))
117 return ERR_PTR(-EPERM);
118
119 for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) {
120 if (!kobj_ns_current_may_mount(type))
121 return ERR_PTR(-EPERM);
122 }
123 }
117 124
118 info = kzalloc(sizeof(*info), GFP_KERNEL);125 info = kzalloc(sizeof(*info), GFP_KERNEL);
119 if (!info)126 if (!info)
include/linux/capability.h+0−1
@@ -210,7 +210,6 @@ extern bool has_ns_capability_noaudit(struct task_struct *t, · 209 unmodified lines
210 struct user_namespace *ns, int cap);210 struct user_namespace *ns, int cap);
211extern bool capable(int cap);211extern bool capable(int cap);
212extern bool ns_capable(struct user_namespace *ns, int cap);212extern bool ns_capable(struct user_namespace *ns, int cap);
213extern bool nsown_capable(int cap);
214extern bool inode_capable(const struct inode *inode, int cap);213extern bool inode_capable(const struct inode *inode, int cap);
215extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap);214extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap);
216 215
include/linux/fs.h+1−0
@@ -1900,6 +1900,7 @@ extern int vfs_ustat(dev_t, struct kstatfs *); · 1899 unmodified lines
1900extern int freeze_super(struct super_block *super);1900extern int freeze_super(struct super_block *super);
1901extern int thaw_super(struct super_block *super);1901extern int thaw_super(struct super_block *super);
1902extern bool our_mnt(struct vfsmount *mnt);1902extern bool our_mnt(struct vfsmount *mnt);
1903extern bool fs_fully_visible(struct file_system_type *);
1903 1904
1904extern int current_umask(void);1905extern int current_umask(void);
1905 1906
include/linux/kobject_ns.h+2−0
@@ -39,6 +39,7 @@ enum kobj_ns_type { · 38 unmodified lines
39 */39 */
40struct kobj_ns_type_operations {40struct kobj_ns_type_operations {
41 enum kobj_ns_type type;41 enum kobj_ns_type type;
42 bool (*current_may_mount)(void);
42 void *(*grab_current_ns)(void);43 void *(*grab_current_ns)(void);
43 const void *(*netlink_ns)(struct sock *sk);44 const void *(*netlink_ns)(struct sock *sk);
44 const void *(*initial_ns)(void);45 const void *(*initial_ns)(void);
@@ -50,6 +51,7 @@ int kobj_ns_type_registered(enum kobj_ns_type type); · 5 unmodified lines
50const struct kobj_ns_type_operations *kobj_child_ns_ops(struct kobject *parent);51const struct kobj_ns_type_operations *kobj_child_ns_ops(struct kobject *parent);
51const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj);52const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj);
52 53
54bool kobj_ns_current_may_mount(enum kobj_ns_type type);
53void *kobj_ns_grab_current(enum kobj_ns_type type);55void *kobj_ns_grab_current(enum kobj_ns_type type);
54const void *kobj_ns_netlink(enum kobj_ns_type type, struct sock *sk);56const void *kobj_ns_netlink(enum kobj_ns_type type, struct sock *sk);
55const void *kobj_ns_initial(enum kobj_ns_type type);57const void *kobj_ns_initial(enum kobj_ns_type type);
include/linux/mount.h+1−0
@@ -48,6 +48,7 @@ struct mnt_namespace; · 47 unmodified lines
48#define MNT_INTERNAL 0x400048#define MNT_INTERNAL 0x4000
49 49
50#define MNT_LOCK_READONLY 0x40000050#define MNT_LOCK_READONLY 0x400000
51#define MNT_LOCKED 0x800000
51 52
52struct vfsmount {53struct vfsmount {
53 struct dentry *mnt_root; /* root of the mounted tree */54 struct dentry *mnt_root; /* root of the mounted tree */
include/linux/user_namespace.h+0−4
@@ -27,8 +27,6 @@ struct user_namespace { · 26 unmodified lines
27 kuid_t owner;27 kuid_t owner;
28 kgid_t group;28 kgid_t group;
29 unsigned int proc_inum;29 unsigned int proc_inum;
30 bool may_mount_sysfs;
31 bool may_mount_proc;
32};30};
33 31
34extern struct user_namespace init_user_ns;32extern struct user_namespace init_user_ns;
@@ -85,6 +83,4 @@ static inline void put_user_ns(struct user_namespace *ns) · 50 unmodified lines
85 83
86#endif84#endif
87 85
88void update_mnt_policy(struct user_namespace *userns);
89
90#endif /* _LINUX_USER_H */86#endif /* _LINUX_USER_H */
ipc/namespace.c+1−1
@@ -171,7 +171,7 @@ static int ipcns_install(struct nsproxy *nsproxy, void *new) · 170 unmodified lines
171{171{
172 struct ipc_namespace *ns = new;172 struct ipc_namespace *ns = new;
173 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) ||173 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) ||
174 !nsown_capable(CAP_SYS_ADMIN))174 !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
175 return -EPERM;175 return -EPERM;
176 176
177 /* Ditch state from the old ipc namespace */177 /* Ditch state from the old ipc namespace */
kernel/capability.c+0−12
@@ -432,18 +432,6 @@ bool capable(int cap) · 431 unmodified lines
432}432}
433EXPORT_SYMBOL(capable);433EXPORT_SYMBOL(capable);
434 434
435/**
436 * nsown_capable - Check superior capability to one's own user_ns
437 * @cap: The capability in question
438 *
439 * Return true if the current task has the given superior capability
440 * targeted at its own user namespace.
441 */
442bool nsown_capable(int cap)
443{
444 return ns_capable(current_user_ns(), cap);
445}
446
447/**435/**
448 * inode_capable - Check superior capability over inode436 * inode_capable - Check superior capability over inode
449 * @inode: The inode in question437 * @inode: The inode in question
kernel/fork.c+0−5
@@ -1824,11 +1824,6 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) · 1823 unmodified lines
1824 */1824 */
1825 if (unshare_flags & CLONE_NEWUSER)1825 if (unshare_flags & CLONE_NEWUSER)
1826 unshare_flags |= CLONE_THREAD | CLONE_FS;1826 unshare_flags |= CLONE_THREAD | CLONE_FS;
1827 /*
1828 * If unsharing a pid namespace must also unshare the thread.
1829 */
1830 if (unshare_flags & CLONE_NEWPID)
1831 unshare_flags |= CLONE_THREAD;
1832 /*1827 /*
1833 * If unsharing a thread from a thread group, must also unshare vm.1828 * If unsharing a thread from a thread group, must also unshare vm.
1834 */1829 */
kernel/groups.c+1−1
@@ -233,7 +233,7 @@ SYSCALL_DEFINE2(setgroups, int, gidsetsize, gid_t __user *, grouplist) · 232 unmodified lines
233 struct group_info *group_info;233 struct group_info *group_info;
234 int retval;234 int retval;
235 235
236 if (!nsown_capable(CAP_SETGID))236 if (!ns_capable(current_user_ns(), CAP_SETGID))
237 return -EPERM;237 return -EPERM;
238 if ((unsigned)gidsetsize > NGROUPS_MAX)238 if ((unsigned)gidsetsize > NGROUPS_MAX)
239 return -EINVAL;239 return -EINVAL;
kernel/nsproxy.c+12−24
@@ -126,22 +126,16 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk) · 125 unmodified lines
126 struct nsproxy *old_ns = tsk->nsproxy;126 struct nsproxy *old_ns = tsk->nsproxy;
127 struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns);127 struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns);
128 struct nsproxy *new_ns;128 struct nsproxy *new_ns;
129 int err = 0;
130 129
131 if (!old_ns)130 if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
131 CLONE_NEWPID | CLONE_NEWNET)))) {
132 get_nsproxy(old_ns);
132 return 0;133 return 0;
133
134 get_nsproxy(old_ns);
135
136 if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
137 CLONE_NEWPID | CLONE_NEWNET)))
138 return 0;
139
140 if (!ns_capable(user_ns, CAP_SYS_ADMIN)) {
141 err = -EPERM;
142 goto out;
143 }134 }
144 135
136 if (!ns_capable(user_ns, CAP_SYS_ADMIN))
137 return -EPERM;
138
145 /*139 /*
146 * CLONE_NEWIPC must detach from the undolist: after switching140 * CLONE_NEWIPC must detach from the undolist: after switching
147 * to a new ipc namespace, the semaphore arrays from the old141 * to a new ipc namespace, the semaphore arrays from the old
@@ -149,22 +143,16 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk) · 1 unmodified line
149 * means share undolist with parent, so we must forbid using143 * means share undolist with parent, so we must forbid using
150 * it along with CLONE_NEWIPC.144 * it along with CLONE_NEWIPC.
151 */145 */
152 if ((flags & CLONE_NEWIPC) && (flags & CLONE_SYSVSEM)) {146 if ((flags & (CLONE_NEWIPC | CLONE_SYSVSEM)) ==
153 err = -EINVAL;147 (CLONE_NEWIPC | CLONE_SYSVSEM))
154 goto out;148 return -EINVAL;
155 }
156 149
157 new_ns = create_new_namespaces(flags, tsk, user_ns, tsk->fs);150 new_ns = create_new_namespaces(flags, tsk, user_ns, tsk->fs);
158 if (IS_ERR(new_ns)) {151 if (IS_ERR(new_ns))
159 err = PTR_ERR(new_ns);152 return PTR_ERR(new_ns);
160 goto out;
161 }
162 153
163 tsk->nsproxy = new_ns;154 tsk->nsproxy = new_ns;
164 155 return 0;
165out:
166 put_nsproxy(old_ns);
167 return err;
168}156}
169 157
170void free_nsproxy(struct nsproxy *ns)158void free_nsproxy(struct nsproxy *ns)
kernel/pid.c+1−0
@@ -265,6 +265,7 @@ void free_pid(struct pid *pid) · 264 unmodified lines
265 struct pid_namespace *ns = upid->ns;265 struct pid_namespace *ns = upid->ns;
266 hlist_del_rcu(&upid->pid_chain);266 hlist_del_rcu(&upid->pid_chain);
267 switch(--ns->nr_hashed) {267 switch(--ns->nr_hashed) {
268 case 2:
268 case 1:269 case 1:
269 /* When all that is left in the pid namespace270 /* When all that is left in the pid namespace
270 * is the reaper wake up the reaper. The reaper271 * is the reaper wake up the reaper. The reaper
kernel/pid_namespace.c+1−1
@@ -329,7 +329,7 @@ static int pidns_install(struct nsproxy *nsproxy, void *ns) · 328 unmodified lines
329 struct pid_namespace *ancestor, *new = ns;329 struct pid_namespace *ancestor, *new = ns;
330 330
331 if (!ns_capable(new->user_ns, CAP_SYS_ADMIN) ||331 if (!ns_capable(new->user_ns, CAP_SYS_ADMIN) ||
332 !nsown_capable(CAP_SYS_ADMIN))332 !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
333 return -EPERM;333 return -EPERM;
334 334
335 /*335 /*
kernel/sys.c+10−10
@@ -337,7 +337,7 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid) · 336 unmodified lines
337 if (rgid != (gid_t) -1) {337 if (rgid != (gid_t) -1) {
338 if (gid_eq(old->gid, krgid) ||338 if (gid_eq(old->gid, krgid) ||
339 gid_eq(old->egid, krgid) ||339 gid_eq(old->egid, krgid) ||
340 nsown_capable(CAP_SETGID))340 ns_capable(old->user_ns, CAP_SETGID))
341 new->gid = krgid;341 new->gid = krgid;
342 else342 else
343 goto error;343 goto error;
@@ -346,7 +346,7 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid) · 2 unmodified lines
346 if (gid_eq(old->gid, kegid) ||346 if (gid_eq(old->gid, kegid) ||
347 gid_eq(old->egid, kegid) ||347 gid_eq(old->egid, kegid) ||
348 gid_eq(old->sgid, kegid) ||348 gid_eq(old->sgid, kegid) ||
349 nsown_capable(CAP_SETGID))349 ns_capable(old->user_ns, CAP_SETGID))
350 new->egid = kegid;350 new->egid = kegid;
351 else351 else
352 goto error;352 goto error;
@@ -387,7 +387,7 @@ SYSCALL_DEFINE1(setgid, gid_t, gid) · 34 unmodified lines
387 old = current_cred();387 old = current_cred();
388 388
389 retval = -EPERM;389 retval = -EPERM;
390 if (nsown_capable(CAP_SETGID))390 if (ns_capable(old->user_ns, CAP_SETGID))
391 new->gid = new->egid = new->sgid = new->fsgid = kgid;391 new->gid = new->egid = new->sgid = new->fsgid = kgid;
392 else if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->sgid))392 else if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->sgid))
393 new->egid = new->fsgid = kgid;393 new->egid = new->fsgid = kgid;
@@ -471,7 +471,7 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid) · 77 unmodified lines
471 new->uid = kruid;471 new->uid = kruid;
472 if (!uid_eq(old->uid, kruid) &&472 if (!uid_eq(old->uid, kruid) &&
473 !uid_eq(old->euid, kruid) &&473 !uid_eq(old->euid, kruid) &&
474 !nsown_capable(CAP_SETUID))474 !ns_capable(old->user_ns, CAP_SETUID))
475 goto error;475 goto error;
476 }476 }
477 477
@@ -480,7 +480,7 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid) · 2 unmodified lines
480 if (!uid_eq(old->uid, keuid) &&480 if (!uid_eq(old->uid, keuid) &&
481 !uid_eq(old->euid, keuid) &&481 !uid_eq(old->euid, keuid) &&
482 !uid_eq(old->suid, keuid) &&482 !uid_eq(old->suid, keuid) &&
483 !nsown_capable(CAP_SETUID))483 !ns_capable(old->user_ns, CAP_SETUID))
484 goto error;484 goto error;
485 }485 }
486 486
@@ -534,7 +534,7 @@ SYSCALL_DEFINE1(setuid, uid_t, uid) · 47 unmodified lines
534 old = current_cred();534 old = current_cred();
535 535
536 retval = -EPERM;536 retval = -EPERM;
537 if (nsown_capable(CAP_SETUID)) {537 if (ns_capable(old->user_ns, CAP_SETUID)) {
538 new->suid = new->uid = kuid;538 new->suid = new->uid = kuid;
539 if (!uid_eq(kuid, old->uid)) {539 if (!uid_eq(kuid, old->uid)) {
540 retval = set_user(new);540 retval = set_user(new);
@@ -591,7 +591,7 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid) · 50 unmodified lines
591 old = current_cred();591 old = current_cred();
592 592
593 retval = -EPERM;593 retval = -EPERM;
594 if (!nsown_capable(CAP_SETUID)) {594 if (!ns_capable(old->user_ns, CAP_SETUID)) {
595 if (ruid != (uid_t) -1 && !uid_eq(kruid, old->uid) &&595 if (ruid != (uid_t) -1 && !uid_eq(kruid, old->uid) &&
596 !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid))596 !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid))
597 goto error;597 goto error;
@@ -673,7 +673,7 @@ SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid) · 75 unmodified lines
673 old = current_cred();673 old = current_cred();
674 674
675 retval = -EPERM;675 retval = -EPERM;
676 if (!nsown_capable(CAP_SETGID)) {676 if (!ns_capable(old->user_ns, CAP_SETGID)) {
677 if (rgid != (gid_t) -1 && !gid_eq(krgid, old->gid) &&677 if (rgid != (gid_t) -1 && !gid_eq(krgid, old->gid) &&
678 !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid))678 !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid))
679 goto error;679 goto error;
@@ -744,7 +744,7 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid) · 64 unmodified lines
744 744
745 if (uid_eq(kuid, old->uid) || uid_eq(kuid, old->euid) ||745 if (uid_eq(kuid, old->uid) || uid_eq(kuid, old->euid) ||
746 uid_eq(kuid, old->suid) || uid_eq(kuid, old->fsuid) ||746 uid_eq(kuid, old->suid) || uid_eq(kuid, old->fsuid) ||
747 nsown_capable(CAP_SETUID)) {747 ns_capable(old->user_ns, CAP_SETUID)) {
748 if (!uid_eq(kuid, old->fsuid)) {748 if (!uid_eq(kuid, old->fsuid)) {
749 new->fsuid = kuid;749 new->fsuid = kuid;
750 if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0)750 if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0)
@@ -783,7 +783,7 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid) · 32 unmodified lines
783 783
784 if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->egid) ||784 if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->egid) ||
785 gid_eq(kgid, old->sgid) || gid_eq(kgid, old->fsgid) ||785 gid_eq(kgid, old->sgid) || gid_eq(kgid, old->fsgid) ||
786 nsown_capable(CAP_SETGID)) {786 ns_capable(old->user_ns, CAP_SETGID)) {
787 if (!gid_eq(kgid, old->fsgid)) {787 if (!gid_eq(kgid, old->fsgid)) {
788 new->fsgid = kgid;788 new->fsgid = kgid;
789 goto change_okay;789 goto change_okay;
kernel/uid16.c+1−1
@@ -176,7 +176,7 @@ SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist) · 175 unmodified lines
176 struct group_info *group_info;176 struct group_info *group_info;
177 int retval;177 int retval;
178 178
179 if (!nsown_capable(CAP_SETGID))179 if (!ns_capable(current_user_ns(), CAP_SETGID))
180 return -EPERM;180 return -EPERM;
181 if ((unsigned)gidsetsize > NGROUPS_MAX)181 if ((unsigned)gidsetsize > NGROUPS_MAX)
182 return -EINVAL;182 return -EINVAL;
kernel/user.c+0−2
@@ -51,8 +51,6 @@ struct user_namespace init_user_ns = { · 50 unmodified lines
51 .owner = GLOBAL_ROOT_UID,51 .owner = GLOBAL_ROOT_UID,
52 .group = GLOBAL_ROOT_GID,52 .group = GLOBAL_ROOT_GID,
53 .proc_inum = PROC_USER_INIT_INO,53 .proc_inum = PROC_USER_INIT_INO,
54 .may_mount_sysfs = true,
55 .may_mount_proc = true,
56};54};
57EXPORT_SYMBOL_GPL(init_user_ns);55EXPORT_SYMBOL_GPL(init_user_ns);
58 56
kernel/user_namespace.c+0−2
@@ -101,8 +101,6 @@ int create_user_ns(struct cred *new) · 100 unmodified lines
101 101
102 set_cred_user_ns(new, ns);102 set_cred_user_ns(new, ns);
103 103
104 update_mnt_policy(ns);
105
106 return 0;104 return 0;
107}105}
108 106
kernel/utsname.c+1−1
@@ -114,7 +114,7 @@ static int utsns_install(struct nsproxy *nsproxy, void *new) · 113 unmodified lines
114 struct uts_namespace *ns = new;114 struct uts_namespace *ns = new;
115 115
116 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) ||116 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) ||
117 !nsown_capable(CAP_SYS_ADMIN))117 !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
118 return -EPERM;118 return -EPERM;
119 119
120 get_uts_ns(ns);120 get_uts_ns(ns);
lib/kobject.c+15−0
@@ -931,6 +931,21 @@ const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj) · 930 unmodified lines
931 return kobj_child_ns_ops(kobj->parent);931 return kobj_child_ns_ops(kobj->parent);
932}932}
933 933
934bool kobj_ns_current_may_mount(enum kobj_ns_type type)
935{
936 bool may_mount = false;
937
938 if (type == KOBJ_NS_TYPE_NONE)
939 return true;
940
941 spin_lock(&kobj_ns_type_lock);
942 if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) &&
943 kobj_ns_ops_tbl[type])
944 may_mount = kobj_ns_ops_tbl[type]->current_may_mount();
945 spin_unlock(&kobj_ns_type_lock);
946
947 return may_mount;
948}
934 949
935void *kobj_ns_grab_current(enum kobj_ns_type type)950void *kobj_ns_grab_current(enum kobj_ns_type type)
936{951{
net/core/net-sysfs.c+8−0
@@ -1196,6 +1196,13 @@ static void remove_queue_kobjects(struct net_device *net) · 1195 unmodified lines
1196#endif1196#endif
1197}1197}
1198 1198
1199static bool net_current_may_mount(void)
1200{
1201 struct net *net = current->nsproxy->net_ns;
1202
1203 return ns_capable(net->user_ns, CAP_SYS_ADMIN);
1204}
1205
1199static void *net_grab_current_ns(void)1206static void *net_grab_current_ns(void)
1200{1207{
1201 struct net *ns = current->nsproxy->net_ns;1208 struct net *ns = current->nsproxy->net_ns;
@@ -1218,6 +1225,7 @@ static const void *net_netlink_ns(struct sock *sk) · 16 unmodified lines
1218 1225
1219struct kobj_ns_type_operations net_ns_type_operations = {1226struct kobj_ns_type_operations net_ns_type_operations = {
1220 .type = KOBJ_NS_TYPE_NET,1227 .type = KOBJ_NS_TYPE_NET,
1228 .current_may_mount = net_current_may_mount,
1221 .grab_current_ns = net_grab_current_ns,1229 .grab_current_ns = net_grab_current_ns,
1222 .netlink_ns = net_netlink_ns,1230 .netlink_ns = net_netlink_ns,
1223 .initial_ns = net_initial_ns,1231 .initial_ns = net_initial_ns,
net/core/net_namespace.c+1−1
@@ -651,7 +651,7 @@ static int netns_install(struct nsproxy *nsproxy, void *ns) · 650 unmodified lines
651 struct net *net = ns;651 struct net *net = ns;
652 652
653 if (!ns_capable(net->user_ns, CAP_SYS_ADMIN) ||653 if (!ns_capable(net->user_ns, CAP_SYS_ADMIN) ||
654 !nsown_capable(CAP_SYS_ADMIN))654 !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
655 return -EPERM;655 return -EPERM;
656 656
657 put_net(nsproxy->net_ns);657 put_net(nsproxy->net_ns);
net/core/scm.c+2−2
@@ -56,9 +56,9 @@ static __inline__ int scm_check_creds(struct ucred *creds) · 55 unmodified lines
56 if ((creds->pid == task_tgid_vnr(current) ||56 if ((creds->pid == task_tgid_vnr(current) ||
57 ns_capable(task_active_pid_ns(current)->user_ns, CAP_SYS_ADMIN)) &&57 ns_capable(task_active_pid_ns(current)->user_ns, CAP_SYS_ADMIN)) &&
58 ((uid_eq(uid, cred->uid) || uid_eq(uid, cred->euid) ||58 ((uid_eq(uid, cred->uid) || uid_eq(uid, cred->euid) ||
59 uid_eq(uid, cred->suid)) || nsown_capable(CAP_SETUID)) &&59 uid_eq(uid, cred->suid)) || ns_capable(cred->user_ns, CAP_SETUID)) &&
60 ((gid_eq(gid, cred->gid) || gid_eq(gid, cred->egid) ||60 ((gid_eq(gid, cred->gid) || gid_eq(gid, cred->egid) ||
61 gid_eq(gid, cred->sgid)) || nsown_capable(CAP_SETGID))) {61 gid_eq(gid, cred->sgid)) || ns_capable(cred->user_ns, CAP_SETGID))) {
62 return 0;62 return 0;
63 }63 }
64 return -EPERM;64 return -EPERM;
security/commoncap.c+5−5
@@ -768,16 +768,16 @@ int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags) · 767 unmodified lines
768 */768 */
769static int cap_safe_nice(struct task_struct *p)769static int cap_safe_nice(struct task_struct *p)
770{770{
771 int is_subset;771 int is_subset, ret = 0;
772 772
773 rcu_read_lock();773 rcu_read_lock();
774 is_subset = cap_issubset(__task_cred(p)->cap_permitted,774 is_subset = cap_issubset(__task_cred(p)->cap_permitted,
775 current_cred()->cap_permitted);775 current_cred()->cap_permitted);
776 if (!is_subset && !ns_capable(__task_cred(p)->user_ns, CAP_SYS_NICE))
777 ret = -EPERM;
776 rcu_read_unlock();778 rcu_read_unlock();
777 779
778 if (!is_subset && !capable(CAP_SYS_NICE))780 return ret;
779 return -EPERM;
780 return 0;
781}781}
782 782
783/**783/**
@@ -824,7 +824,7 @@ int cap_task_setnice(struct task_struct *p, int nice) · 40 unmodified lines
824 */824 */
825static long cap_prctl_drop(struct cred *new, unsigned long cap)825static long cap_prctl_drop(struct cred *new, unsigned long cap)
826{826{
827 if (!capable(CAP_SETPCAP))827 if (!ns_capable(current_user_ns(), CAP_SETPCAP))
828 return -EPERM;828 return -EPERM;
829 if (!cap_valid(cap))829 if (!cap_valid(cap))
830 return -EINVAL;830 return -EINVAL;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t