check_mnt() breaks namespaces
Hi Andrew!
the check_mnt() in do_add_mount() breaks namespaces in that way, that it forbids mounting single sb filesystems (like procfs) to be mounted in different namespaces ...
I guess this is unintentional, but who knows ... (this was introduced in 2.6.8-rc1, 2.6.7-bk20 works as expected)
something like this (untested) fixes? it ...
fs/namei.c 2004-07-12 14:59:08.000000000 +0200 renamed from fs/namei.c 2004-07-12 14:47:08.000000000 +0200 +0 -3
@@ -794,7 +819,5 @@ int do_add_mount(struct vfsmount *newmnt ; - err = -EINVAL; - if (!check_mnt(nd->mnt)) - goto unlock; /* Refuse the same filesystem on the same mount point */ err = -EBUSY;
best,
Herbert
It's not check_mnt(), it's breakage in copy_namespace().
It forgets to switch new field (->mnt_namespace) in the vfsmounts of new namespace.
namespace.c renamed from RC8-rc2/fs/namespace.c +13 -11
@@ -1037,6 +1037,7 @@struct namespace *new_ns;struct vfsmount *rootmnt =NULL , *pwdmnt =NULL , *altrootmnt =NULL ;struct fs_struct *fs = tsk->fs; +struct vfsmount *p, *q;if (!namespace)return 0 ;
@@ -1071,14 +1072,16 @@list_add_tail (&new_ns->list, &new_ns->root->mnt_list);spin_unlock (&vfsmount_lock); -/* Second pass: switch the tsk->fs->* elements */ -if (fs) { -struct vfsmount *p, *q; -write_lock (&fs->lock); - - p = namespace->root; - q = new_ns->root; -while (p) { +/* +* Second pass: switch the tsk->fs->* elements and mark new vfsmounts +* as belonging to new namespace. We have already acquired a private +* fs_struct, so tsk->fs->lock is not needed. +*/ + p = namespace->root; + q = new_ns->root; +while (p) { + q->mnt_namespace = new_ns; +if (fs) {if (p == fs->rootmnt) { rootmnt = p; fs->rootmnt =mntget (q);
@@ -1091,10 +1094,9 @@ altrootmnt = p; fs->altrootmnt =mntget (q); } - p =next_mnt (p, namespace->root); - q =next_mnt (q, new_ns->root); } -write_unlock (&fs->lock); + p =next_mnt (p, namespace->root); + q =next_mnt (q, new_ns->root); }up_write (&tsk->namespace->sem);