diff options
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 74 |
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 | ||
2874 | static void free_mnt_ns(struct mnt_namespace *ns) | 2874 | static 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 | */ |
2889 | static atomic64_t mnt_ns_seq = ATOMIC64_INIT(1); | 2890 | static atomic64_t mnt_ns_seq = ATOMIC64_INIT(1); |
2890 | 2891 | ||
2891 | static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns) | 2892 | static 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 | /** | 3006 | struct 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 | */ | ||
3010 | static 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 | |||
3025 | struct 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: | |||
3243 | static void __init init_mount_tree(void) | 3231 | static 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 | ||