Commit dc77fe13 authored by Andries E. Brouwer's avatar Andries E. Brouwer Committed by Linus Torvalds

[PATCH] namespace fix

After

    # mount --rbind /tmp /mnt

(on 2.5.68) I have a corrupted namespace. Umounting /mnt fails,
and /proc/mounts contains

    ...
    /dev/root /mnt ext3 rw 0 0
    proc /mnt/proc proc rw 0 0
    usbfs /mnt/proc/bus/usb usbfs rw 0 0
    /dev/hdb5 /mnt/usr reiserfs rw 0 0
    ...

where of course no directories /mnt/proc or /mnt/usr exist.

This is caused by the fact that copy_tree() thinks that the dentry
it is called with is the root of the filesystem. If it is not,
confusion arose.

This patch fixes this confusion.
parent c4717755
...@@ -418,36 +418,54 @@ static int mount_is_safe(struct nameidata *nd) ...@@ -418,36 +418,54 @@ static int mount_is_safe(struct nameidata *nd)
#endif #endif
} }
static int
lives_below_in_same_fs(struct dentry *d, struct dentry *dentry)
{
while (1) {
if (d == dentry)
return 1;
if (d == NULL || d == d->d_parent)
return 0;
d = d->d_parent;
}
}
static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry) static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry)
{ {
struct vfsmount *p, *next, *q, *res; struct vfsmount *res, *p, *q, *r, *s;
struct list_head *h;
struct nameidata nd; struct nameidata nd;
p = mnt; res = q = clone_mnt(mnt, dentry);
res = nd.mnt = q = clone_mnt(p, dentry);
if (!q) if (!q)
goto Enomem; goto Enomem;
q->mnt_parent = q; q->mnt_mountpoint = mnt->mnt_mountpoint;
q->mnt_mountpoint = p->mnt_mountpoint;
while ( (next = next_mnt(p, mnt)) != NULL) { p = mnt;
while (p != next->mnt_parent) { for (h = mnt->mnt_mounts.next; h != &mnt->mnt_mounts; h = h->next) {
p = p->mnt_parent; r = list_entry(h, struct vfsmount, mnt_child);
q = q->mnt_parent; if (!lives_below_in_same_fs(r->mnt_mountpoint, dentry))
continue;
for (s = r; s; s = next_mnt(s, r)) {
while (p != s->mnt_parent) {
p = p->mnt_parent;
q = q->mnt_parent;
}
p = s;
nd.mnt = q;
nd.dentry = p->mnt_mountpoint;
q = clone_mnt(p, p->mnt_root);
if (!q)
goto Enomem;
spin_lock(&dcache_lock);
list_add_tail(&q->mnt_list, &res->mnt_list);
attach_mnt(q, &nd);
spin_unlock(&dcache_lock);
} }
p = next;
nd.mnt = q;
nd.dentry = p->mnt_mountpoint;
q = clone_mnt(p, p->mnt_root);
if (!q)
goto Enomem;
spin_lock(&dcache_lock);
list_add_tail(&q->mnt_list, &res->mnt_list);
attach_mnt(q, &nd);
spin_unlock(&dcache_lock);
} }
return res; return res;
Enomem: Enomem:
if (res) { if (res) {
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
umount_tree(res); umount_tree(res);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment