[PATCH] namei fixes (15/19)
authorAl Viro <viro@www.linux.org.uk>
Mon, 6 Jun 2005 20:36:11 +0000 (13:36 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 6 Jun 2005 21:42:27 +0000 (14:42 -0700)
Getting rid of sloppy logics:

a) in do_follow_link() we have the wrong vfsmount dropped if our symlink
had been mounted on something.  Currently it worls only because we never
get such situation (modulo filesystem playing dirty tricks on us).  And
it obfuscates already convoluted logics...

b) same goes for open_namei().

c) in __link_path_walk() we have another "it should never happen" sloppiness -
out_dput: there does double-free on underlying vfsmount and leaks the covering
one if we hit it just after crossing a mountpoint.  Again, wrong vfsmount
getting dropped.

d) another too-early-mntput() race - in do_follow_mount() we need to postpone
conditional mntput(path->mnt) until after dput(path->dentry).  Again, this one
happens only in it-currently-never-happens-unless-some-fs-plays-dirty
scenario...

Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/namei.c

index 411bb3243c36fab5f302e0d055466149e4a55fa5..6a884682b0a7e8a7280427cdaeb1c5fd70f21f9f 100644 (file)
@@ -544,15 +544,15 @@ static inline int do_follow_link(struct path *path, struct nameidata *nd)
        current->total_link_count++;
        nd->depth++;
        if (path->mnt != nd->mnt)
-               mntput(nd->mnt);
+               mntput(path->mnt);
        err = __do_follow_link(path, nd);
        current->link_count--;
        nd->depth--;
        return err;
 loop:
-       if (path->mnt != nd->mnt)
-               mntput(nd->mnt);
        dput(path->dentry);
+       if (path->mnt != nd->mnt)
+               mntput(path->mnt);
        path_release(nd);
        return err;
 }
@@ -906,7 +906,7 @@ return_base:
 out_dput:
                dput(next.dentry);
                if (nd->mnt != next.mnt)
-                       mntput(nd->mnt);
+                       mntput(next.mnt);
                break;
        }
        path_release(nd);
@@ -1551,8 +1551,7 @@ do_link:
        if (error)
                goto exit_dput;
        if (nd->mnt != path.mnt)
-               mntput(nd->mnt);
-       nd->mnt = path.mnt;
+               mntput(path.mnt);
        error = __do_follow_link(&path, nd);
        if (error)
                return error;