summaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c74
1 files changed, 35 insertions, 39 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 9ed2f2930dfd..f0b8a8ca08df 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2873,7 +2873,8 @@ static void dec_mnt_namespaces(struct ucounts *ucounts)
2873 2873
2874static void free_mnt_ns(struct mnt_namespace *ns) 2874static void free_mnt_ns(struct mnt_namespace *ns)
2875{ 2875{
2876 ns_free_inum(&ns->ns); 2876 if (!is_anon_ns(ns))
2877 ns_free_inum(&ns->ns);
2877 dec_mnt_namespaces(ns->ucounts); 2878 dec_mnt_namespaces(ns->ucounts);
2878 put_user_ns(ns->user_ns); 2879 put_user_ns(ns->user_ns);
2879 kfree(ns); 2880 kfree(ns);
@@ -2888,7 +2889,7 @@ static void free_mnt_ns(struct mnt_namespace *ns)
2888 */ 2889 */
2889static atomic64_t mnt_ns_seq = ATOMIC64_INIT(1); 2890static atomic64_t mnt_ns_seq = ATOMIC64_INIT(1);
2890 2891
2891static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns) 2892static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns, bool anon)
2892{ 2893{
2893 struct mnt_namespace *new_ns; 2894 struct mnt_namespace *new_ns;
2894 struct ucounts *ucounts; 2895 struct ucounts *ucounts;
@@ -2898,28 +2899,27 @@ static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
2898 if (!ucounts) 2899 if (!ucounts)
2899 return ERR_PTR(-ENOSPC); 2900 return ERR_PTR(-ENOSPC);
2900 2901
2901 new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL); 2902 new_ns = kzalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
2902 if (!new_ns) { 2903 if (!new_ns) {
2903 dec_mnt_namespaces(ucounts); 2904 dec_mnt_namespaces(ucounts);
2904 return ERR_PTR(-ENOMEM); 2905 return ERR_PTR(-ENOMEM);
2905 } 2906 }
2906 ret = ns_alloc_inum(&new_ns->ns); 2907 if (!anon) {
2907 if (ret) { 2908 ret = ns_alloc_inum(&new_ns->ns);
2908 kfree(new_ns); 2909 if (ret) {
2909 dec_mnt_namespaces(ucounts); 2910 kfree(new_ns);
2910 return ERR_PTR(ret); 2911 dec_mnt_namespaces(ucounts);
2912 return ERR_PTR(ret);
2913 }
2911 } 2914 }
2912 new_ns->ns.ops = &mntns_operations; 2915 new_ns->ns.ops = &mntns_operations;
2913 new_ns->seq = atomic64_add_return(1, &mnt_ns_seq); 2916 if (!anon)
2917 new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
2914 atomic_set(&new_ns->count, 1); 2918 atomic_set(&new_ns->count, 1);
2915 new_ns->root = NULL;
2916 INIT_LIST_HEAD(&new_ns->list); 2919 INIT_LIST_HEAD(&new_ns->list);
2917 init_waitqueue_head(&new_ns->poll); 2920 init_waitqueue_head(&new_ns->poll);
2918 new_ns->event = 0;
2919 new_ns->user_ns = get_user_ns(user_ns); 2921 new_ns->user_ns = get_user_ns(user_ns);
2920 new_ns->ucounts = ucounts; 2922 new_ns->ucounts = ucounts;
2921 new_ns->mounts = 0;
2922 new_ns->pending_mounts = 0;
2923 return new_ns; 2923 return new_ns;
2924} 2924}
2925 2925
@@ -2943,7 +2943,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
2943 2943
2944 old = ns->root; 2944 old = ns->root;
2945 2945
2946 new_ns = alloc_mnt_ns(user_ns); 2946 new_ns = alloc_mnt_ns(user_ns, false);
2947 if (IS_ERR(new_ns)) 2947 if (IS_ERR(new_ns))
2948 return new_ns; 2948 return new_ns;
2949 2949
@@ -3003,37 +3003,25 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
3003 return new_ns; 3003 return new_ns;
3004} 3004}
3005 3005
3006/** 3006struct dentry *mount_subtree(struct vfsmount *m, const char *name)
3007 * create_mnt_ns - creates a private namespace and adds a root filesystem
3008 * @mnt: pointer to the new root filesystem mountpoint
3009 */
3010static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)
3011{
3012 struct mnt_namespace *new_ns = alloc_mnt_ns(&init_user_ns);
3013 if (!IS_ERR(new_ns)) {
3014 struct mount *mnt = real_mount(m);
3015 mnt->mnt_ns = new_ns;
3016 new_ns->root = mnt;
3017 new_ns->mounts++;
3018 list_add(&mnt->mnt_list, &new_ns->list);
3019 } else {
3020 mntput(m);
3021 }
3022 return new_ns;
3023}
3024
3025struct dentry *mount_subtree(struct vfsmount *mnt, const char *name)
3026{ 3007{
3008 struct mount *mnt = real_mount(m);
3027 struct mnt_namespace *ns; 3009 struct mnt_namespace *ns;
3028 struct super_block *s; 3010 struct super_block *s;
3029 struct path path; 3011 struct path path;
3030 int err; 3012 int err;
3031 3013
3032 ns = create_mnt_ns(mnt); 3014 ns = alloc_mnt_ns(&init_user_ns, true);
3033 if (IS_ERR(ns)) 3015 if (IS_ERR(ns)) {
3016 mntput(m);
3034 return ERR_CAST(ns); 3017 return ERR_CAST(ns);
3018 }
3019 mnt->mnt_ns = ns;
3020 ns->root = mnt;
3021 ns->mounts++;
3022 list_add(&mnt->mnt_list, &ns->list);
3035 3023
3036 err = vfs_path_lookup(mnt->mnt_root, mnt, 3024 err = vfs_path_lookup(m->mnt_root, m,
3037 name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path); 3025 name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);
3038 3026
3039 put_mnt_ns(ns); 3027 put_mnt_ns(ns);
@@ -3243,6 +3231,7 @@ out0:
3243static void __init init_mount_tree(void) 3231static void __init init_mount_tree(void)
3244{ 3232{
3245 struct vfsmount *mnt; 3233 struct vfsmount *mnt;
3234 struct mount *m;
3246 struct mnt_namespace *ns; 3235 struct mnt_namespace *ns;
3247 struct path root; 3236 struct path root;
3248 struct file_system_type *type; 3237 struct file_system_type *type;
@@ -3255,10 +3244,14 @@ static void __init init_mount_tree(void)
3255 if (IS_ERR(mnt)) 3244 if (IS_ERR(mnt))
3256 panic("Can't create rootfs"); 3245 panic("Can't create rootfs");
3257 3246
3258 ns = create_mnt_ns(mnt); 3247 ns = alloc_mnt_ns(&init_user_ns, false);
3259 if (IS_ERR(ns)) 3248 if (IS_ERR(ns))
3260 panic("Can't allocate initial namespace"); 3249 panic("Can't allocate initial namespace");
3261 3250 m = real_mount(mnt);
3251 m->mnt_ns = ns;
3252 ns->root = m;
3253 ns->mounts = 1;
3254 list_add(&m->mnt_list, &ns->list);
3262 init_task.nsproxy->mnt_ns = ns; 3255 init_task.nsproxy->mnt_ns = ns;
3263 get_mnt_ns(ns); 3256 get_mnt_ns(ns);
3264 3257
@@ -3499,6 +3492,9 @@ static int mntns_install(struct nsproxy *nsproxy, struct ns_common *ns)
3499 !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) 3492 !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
3500 return -EPERM; 3493 return -EPERM;
3501 3494
3495 if (is_anon_ns(mnt_ns))
3496 return -EINVAL;
3497
3502 if (fs->users != 1) 3498 if (fs->users != 1)
3503 return -EINVAL; 3499 return -EINVAL;
3504 3500