diff options
-rw-r--r-- | fs/namespace.c | 21 | ||||
-rw-r--r-- | fs/proc/root.c | 4 | ||||
-rw-r--r-- | fs/sysfs/mount.c | 4 | ||||
-rw-r--r-- | include/linux/user_namespace.h | 4 | ||||
-rw-r--r-- | kernel/user.c | 2 | ||||
-rw-r--r-- | kernel/user_namespace.c | 2 |
6 files changed, 37 insertions, 0 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 968d4c5eae03..d581e45c0a9f 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -2763,6 +2763,27 @@ bool current_chrooted(void) | |||
2763 | return chrooted; | 2763 | return chrooted; |
2764 | } | 2764 | } |
2765 | 2765 | ||
2766 | void update_mnt_policy(struct user_namespace *userns) | ||
2767 | { | ||
2768 | struct mnt_namespace *ns = current->nsproxy->mnt_ns; | ||
2769 | struct mount *mnt; | ||
2770 | |||
2771 | down_read(&namespace_sem); | ||
2772 | list_for_each_entry(mnt, &ns->list, mnt_list) { | ||
2773 | switch (mnt->mnt.mnt_sb->s_magic) { | ||
2774 | case SYSFS_MAGIC: | ||
2775 | userns->may_mount_sysfs = true; | ||
2776 | break; | ||
2777 | case PROC_SUPER_MAGIC: | ||
2778 | userns->may_mount_proc = true; | ||
2779 | break; | ||
2780 | } | ||
2781 | if (userns->may_mount_sysfs && userns->may_mount_proc) | ||
2782 | break; | ||
2783 | } | ||
2784 | up_read(&namespace_sem); | ||
2785 | } | ||
2786 | |||
2766 | static void *mntns_get(struct task_struct *task) | 2787 | static void *mntns_get(struct task_struct *task) |
2767 | { | 2788 | { |
2768 | struct mnt_namespace *ns = NULL; | 2789 | struct mnt_namespace *ns = NULL; |
diff --git a/fs/proc/root.c b/fs/proc/root.c index c6e9fac26bac..9c7fab1d23f0 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/sched.h> | 16 | #include <linux/sched.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/bitops.h> | 18 | #include <linux/bitops.h> |
19 | #include <linux/user_namespace.h> | ||
19 | #include <linux/mount.h> | 20 | #include <linux/mount.h> |
20 | #include <linux/pid_namespace.h> | 21 | #include <linux/pid_namespace.h> |
21 | #include <linux/parser.h> | 22 | #include <linux/parser.h> |
@@ -108,6 +109,9 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, | |||
108 | } else { | 109 | } else { |
109 | ns = task_active_pid_ns(current); | 110 | ns = task_active_pid_ns(current); |
110 | options = data; | 111 | options = data; |
112 | |||
113 | if (!current_user_ns()->may_mount_proc) | ||
114 | return ERR_PTR(-EPERM); | ||
111 | } | 115 | } |
112 | 116 | ||
113 | sb = sget(fs_type, proc_test_super, proc_set_super, flags, ns); | 117 | sb = sget(fs_type, proc_test_super, proc_set_super, flags, ns); |
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 8d924b5ec733..afd83273e6ce 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/magic.h> | 20 | #include <linux/magic.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/user_namespace.h> | ||
22 | 23 | ||
23 | #include "sysfs.h" | 24 | #include "sysfs.h" |
24 | 25 | ||
@@ -111,6 +112,9 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type, | |||
111 | struct super_block *sb; | 112 | struct super_block *sb; |
112 | int error; | 113 | int error; |
113 | 114 | ||
115 | if (!(flags & MS_KERNMOUNT) && !current_user_ns()->may_mount_sysfs) | ||
116 | return ERR_PTR(-EPERM); | ||
117 | |||
114 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 118 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
115 | if (!info) | 119 | if (!info) |
116 | return ERR_PTR(-ENOMEM); | 120 | return ERR_PTR(-ENOMEM); |
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index 4ce009324933..b6b215f13b45 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h | |||
@@ -26,6 +26,8 @@ struct user_namespace { | |||
26 | kuid_t owner; | 26 | kuid_t owner; |
27 | kgid_t group; | 27 | kgid_t group; |
28 | unsigned int proc_inum; | 28 | unsigned int proc_inum; |
29 | bool may_mount_sysfs; | ||
30 | bool may_mount_proc; | ||
29 | }; | 31 | }; |
30 | 32 | ||
31 | extern struct user_namespace init_user_ns; | 33 | extern struct user_namespace init_user_ns; |
@@ -82,4 +84,6 @@ static inline void put_user_ns(struct user_namespace *ns) | |||
82 | 84 | ||
83 | #endif | 85 | #endif |
84 | 86 | ||
87 | void update_mnt_policy(struct user_namespace *userns); | ||
88 | |||
85 | #endif /* _LINUX_USER_H */ | 89 | #endif /* _LINUX_USER_H */ |
diff --git a/kernel/user.c b/kernel/user.c index e81978e8c03b..8e635a18ab52 100644 --- a/kernel/user.c +++ b/kernel/user.c | |||
@@ -51,6 +51,8 @@ struct user_namespace init_user_ns = { | |||
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, | ||
54 | }; | 56 | }; |
55 | EXPORT_SYMBOL_GPL(init_user_ns); | 57 | EXPORT_SYMBOL_GPL(init_user_ns); |
56 | 58 | ||
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 0f1e42884577..a54f26f82eb2 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c | |||
@@ -96,6 +96,8 @@ int create_user_ns(struct cred *new) | |||
96 | 96 | ||
97 | set_cred_user_ns(new, ns); | 97 | set_cred_user_ns(new, ns); |
98 | 98 | ||
99 | update_mnt_policy(ns); | ||
100 | |||
99 | return 0; | 101 | return 0; |
100 | } | 102 | } |
101 | 103 | ||