summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2019-01-30 13:30:21 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2019-01-30 17:44:07 -0500
commit74e831221cfd79460ec11c1b641093863f0ef3ce (patch)
tree270fb98f1e5bebd78a90554690a3ffe560f3690f
parent3bd045cc9c4be2049602b47505256b43908b4e2f (diff)
saner handling of temporary namespaces
mount_subtree() creates (and soon destroys) a temporary namespace, so that automounts could function normally. These beasts should never become anyone's current namespaces; they don't, but it would be better to make prevention of that more straightforward. And since they don't become anyone's current namespace, we don't need to bother with reserving procfs inums for those. Teach alloc_mnt_ns() to skip inum allocation if told so, adjust put_mnt_ns() accordingly, make mount_subtree() use temporary (anon) namespace. is_anon_ns() checks if a namespace is such. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/mount.h5
-rw-r--r--fs/namespace.c74
2 files changed, 40 insertions, 39 deletions
diff --git a/fs/mount.h b/fs/mount.h
index f39bc9da4d73..6250de544760 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -146,3 +146,8 @@ static inline bool is_local_mountpoint(struct dentry *dentry)
146 146
147 return __is_local_mountpoint(dentry); 147 return __is_local_mountpoint(dentry);
148} 148}
149
150static inline bool is_anon_ns(struct mnt_namespace *ns)
151{
152 return ns->seq == 0;
153}
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