From: Alexander Viro <viro@math.psu.edu>
To: Linus Torvalds <torvalds@transmeta.com>
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH] lazy umount (3/4)
Date: Fri, 14 Sep 2001 15:03:12 -0400 (EDT) [thread overview]
Message-ID: <Pine.GSO.4.21.0109141502430.11172-100000@weyl.math.psu.edu> (raw)
In-Reply-To: <Pine.GSO.4.21.0109141502090.11172-100000@weyl.math.psu.edu>
Part 3/4:
New function - check_mnt(). Checks that vfsmount is an ancestor
of root_vfsmnt. Calls added - since we are going to do lazy umount we
should take care of mounting on something that is busy, but already umounted.
Fixed leak in pivot_root(2)
diff -urN S10-pre9-root_vfsmnt/fs/super.c S10-pre9-check_mnt/fs/super.c
--- S10-pre9-root_vfsmnt/fs/super.c Fri Sep 14 14:03:34 2001
+++ S10-pre9-check_mnt/fs/super.c Fri Sep 14 14:04:01 2001
@@ -327,6 +327,15 @@
return p;
}
+static int check_mnt(struct vfsmount *mnt)
+{
+ spin_lock(&dcache_lock);
+ while (mnt->mnt_parent != mnt)
+ mnt = mnt->mnt_parent;
+ spin_unlock(&dcache_lock);
+ return mnt == root_vfsmnt;
+}
+
static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd)
{
old_nd->dentry = mnt->mnt_mountpoint;
@@ -1226,6 +1235,8 @@
retval = -EINVAL;
if (nd.dentry != nd.mnt->mnt_root)
goto dput_and_out;
+ if (!check_mnt(nd.mnt))
+ goto dput_and_out;
retval = -EPERM;
if (!capable(CAP_SYS_ADMIN) && current->uid!=nd.mnt->mnt_owner)
@@ -1277,7 +1288,7 @@
static int do_loopback(struct nameidata *nd, char *old_name)
{
struct nameidata old_nd;
- struct vfsmount *mnt;
+ struct vfsmount *mnt = NULL;
int err;
err = mount_is_safe(nd);
@@ -1293,12 +1304,16 @@
return err;
down(&mount_sem);
- err = -ENOMEM;
- mnt = clone_mnt(old_nd.mnt, old_nd.dentry);
+ err = -EINVAL;
+ if (check_mnt(nd->mnt)) {
+ err = -ENOMEM;
+ mnt = clone_mnt(old_nd.mnt, old_nd.dentry);
+ }
if (mnt) {
err = graft_tree(mnt, nd);
mntput(mnt);
}
+
up(&mount_sem);
path_release(&old_nd);
return err;
@@ -1318,6 +1333,9 @@
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
+ if (!check_mnt(nd->mnt))
+ return -EINVAL;
+
if (nd->dentry != nd->mnt->mnt_root)
return -EINVAL;
@@ -1396,27 +1414,31 @@
int mnt_flags, char *name, void *data)
{
struct vfsmount *mnt = do_kern_mount(type, flags, name, data);
- int retval = PTR_ERR(mnt);
+ int err = PTR_ERR(mnt);
if (IS_ERR(mnt))
goto out;
- mnt->mnt_flags = mnt_flags;
-
down(&mount_sem);
/* Something was mounted here while we slept */
while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry))
;
+ err = -EINVAL;
+ if (!check_mnt(nd->mnt))
+ goto unlock;
/* Refuse the same filesystem on the same mount point */
+ err = -EBUSY;
if (nd->mnt->mnt_sb == mnt->mnt_sb && nd->mnt->mnt_root == nd->dentry)
- retval = -EBUSY;
- else
- retval = graft_tree(mnt, nd);
+ goto unlock;
+
+ mnt->mnt_flags = mnt_flags;
+ err = graft_tree(mnt, nd);
+unlock:
up(&mount_sem);
mntput(mnt);
out:
- return retval;
+ return err;
}
static int copy_mount_options (const void *data, unsigned long *where)
@@ -1772,10 +1794,8 @@
asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
{
- struct dentry *root;
- struct vfsmount *root_mnt;
struct vfsmount *tmp;
- struct nameidata new_nd, old_nd, parent_nd, root_parent;
+ struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd;
char *name;
int error;
@@ -1794,11 +1814,14 @@
putname(name);
if (error)
goto out0;
+ error = -EINVAL;
+ if (!check_mnt(new_nd.mnt))
+ goto out1;
name = getname(put_old);
error = PTR_ERR(name);
if (IS_ERR(name))
- goto out0;
+ goto out1;
error = 0;
if (path_init(name, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd))
error = path_walk(name, &old_nd);
@@ -1807,11 +1830,14 @@
goto out1;
read_lock(¤t->fs->lock);
- root_mnt = mntget(current->fs->rootmnt);
- root = dget(current->fs->root);
+ user_nd.mnt = mntget(current->fs->rootmnt);
+ user_nd.dentry = dget(current->fs->root);
read_unlock(¤t->fs->lock);
down(&mount_sem);
down(&old_nd.dentry->d_inode->i_zombie);
+ error = -EINVAL;
+ if (!check_mnt(user_nd.mnt))
+ goto out2;
error = -ENOENT;
if (IS_DEADDIR(new_nd.dentry->d_inode))
goto out2;
@@ -1820,10 +1846,10 @@
if (d_unhashed(old_nd.dentry) && !IS_ROOT(old_nd.dentry))
goto out2;
error = -EBUSY;
- if (new_nd.mnt == root_mnt || old_nd.mnt == root_mnt)
+ if (new_nd.mnt == user_nd.mnt || old_nd.mnt == user_nd.mnt)
goto out2; /* loop */
error = -EINVAL;
- if (root_mnt->mnt_root != root)
+ if (user_nd.mnt->mnt_root != user_nd.dentry)
goto out2;
if (new_nd.mnt->mnt_root != new_nd.dentry)
goto out2; /* not a mountpoint */
@@ -1842,19 +1868,18 @@
} else if (!is_subdir(old_nd.dentry, new_nd.dentry))
goto out3;
detach_mnt(new_nd.mnt, &parent_nd);
- detach_mnt(root_mnt, &root_parent);
- attach_mnt(root_mnt, &old_nd);
+ detach_mnt(user_nd.mnt, &root_parent);
+ attach_mnt(user_nd.mnt, &old_nd);
attach_mnt(new_nd.mnt, &root_parent);
spin_unlock(&dcache_lock);
- chroot_fs_refs(root,root_mnt,new_nd.dentry,new_nd.mnt);
+ chroot_fs_refs(user_nd.dentry,user_nd.mnt,new_nd.dentry,new_nd.mnt);
error = 0;
path_release(&root_parent);
path_release(&parent_nd);
out2:
up(&old_nd.dentry->d_inode->i_zombie);
up(&mount_sem);
- dput(root);
- mntput(root_mnt);
+ path_release(&user_nd);
path_release(&old_nd);
out1:
path_release(&new_nd);
next prev parent reply other threads:[~2001-09-14 19:03 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2001-09-14 19:01 [PATCH] lazy umount (1/4) Alexander Viro
2001-09-14 19:02 ` [PATCH] lazy umount (2/4) Alexander Viro
2001-09-14 19:03 ` Alexander Viro [this message]
2001-09-14 19:03 ` [PATCH] lazy umount (4/4) Alexander Viro
2001-09-14 20:43 ` [PATCH] lazy umount (1/4) Linus Torvalds
2001-09-14 20:54 ` Alexander Viro
2001-09-15 12:32 ` jlnance
2001-09-15 20:51 ` Mike Fedyk
2001-09-17 10:06 ` Matthias Andree
2001-09-16 16:37 ` Alex Stewart
2001-09-17 6:57 ` Forced umount (was lazy umount) Ville Herva
2001-09-17 7:03 ` Aaron Lehmann
2001-09-17 8:38 ` Alexander Viro
2001-09-17 10:21 ` Matthias Andree
2001-09-17 10:47 ` Tigran Aivazian
2001-09-17 23:21 ` Alex Stewart
2001-09-17 23:23 ` Xavier Bestel
2001-09-18 1:04 ` Alex Stewart
2001-09-18 20:19 ` Pavel Machek
2001-09-17 8:29 ` Xavier Bestel
2001-09-17 8:39 ` Alexander Viro
2001-09-17 10:04 ` [PATCH] lazy umount (1/4) Matthias Andree
2001-09-17 12:13 ` Alan Cox
2001-09-18 0:24 ` Alex Stewart
2001-09-18 0:39 ` Matthias Andree
2001-09-18 8:56 ` Alexander Viro
2001-09-18 9:08 ` Matthias Andree
2001-09-18 13:03 ` Alan Cox
2001-09-18 9:07 ` David Woodhouse
2001-09-17 14:43 ` David Woodhouse
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Pine.GSO.4.21.0109141502430.11172-100000@weyl.math.psu.edu \
--to=viro@math.psu.edu \
--cc=linux-kernel@vger.kernel.org \
--cc=torvalds@transmeta.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).