Re: [bug-2.3.99-pre7-8] running fuser leaks mnt_count of /proc

From: Alexander Viro (aviro@redhat.com)
Date: Tue May 09 2000 - 16:51:37 EDT

  • Next message: Linda Walsh: "Re: (MAC/DAC) RE: Future Linux devel. Kernels"

    On Tue, 9 May 2000, Tigran Aivazian wrote:

    > On Tue, 9 May 2000, Alexander Viro wrote:
    > > On Tue, 9 May 2000, Tigran Aivazian wrote:
    > > > Just try runnning fuser (on any filesystem) and watch the mnt->mnt_count
    > > > of /proc (of the real entry, not the kern_mounted one) grow steadily by
    > > > one each time.
    > >
    > > How quaint... chdir("/proc/self/fd"); gets the process into the state
    > > where it will correctly deal with further chdir() calls, but fail to
    > > release fs_struct (contents?) upon the exit. It looks like a change of
    > > some state: been there once and that's it - you are doomed. WTF???
    > > More coffee needed - it's getting seriously weird...
    >
    > indeed, the reason it is so is because once we chdir("/proc/self/fs") (or
    > any directory name containing that e.g. "/proc/self/fd/../..") our
    > fs->count gets incremented one extra time so not only we leak /proc's
    > mnt_count but also root's, i.e. the whole chunk of code in
    > __put_fs_struct() is never executed.
    >
    > So, the question is - why/where do we increment fs->count the extra time?
    >
    > Regards,
    > Tigran
    >
    Try that:

    diff -urN linux-2.3.99-pre7-8/fs/proc/base.c linux-bird.vfs-fix/fs/proc/base.c
    --- linux-2.3.99-pre7-8/fs/proc/base.c Tue May 9 16:15:42 2000
    +++ linux-bird.vfs-fix/fs/proc/base.c Tue May 9 16:47:34 2000
    @@ -121,6 +121,7 @@
                     *mnt = mntget(fs->rootmnt);
                     *dentry = dget(fs->root);
                     result = 0;
    + put_fs_struct(fs);
             }
             return result;
     }
    @@ -446,18 +447,19 @@
     {
             int error;
             struct inode *inode = dentry->d_inode;
    - struct vfsmount *mnt;
    + struct dentry *de;
    + struct vfsmount *mnt = NULL;
     
             error = proc_permission(inode, MAY_EXEC);
             if (error)
                     goto out;
     
    - error = inode->u.proc_i.op.proc_get_link(inode, &dentry, &mnt);
    + error = inode->u.proc_i.op.proc_get_link(inode, &de, &mnt);
             if (error)
                     goto out;
     
    - error = do_proc_readlink(dentry, mnt, buffer, buflen);
    - dput(dentry);
    + error = do_proc_readlink(de, mnt, buffer, buflen);
    + dput(de);
             mntput(mnt);
     out:
             return error;
    diff -urN linux-2.3.99-pre7-8/fs/super.c linux-bird.vfs-fix/fs/super.c
    --- linux-2.3.99-pre7-8/fs/super.c Tue May 9 16:15:42 2000
    +++ linux-bird.vfs-fix/fs/super.c Tue May 9 16:37:52 2000
    @@ -949,7 +949,7 @@
             }
     
             if (mnt->mnt_instances.next != mnt->mnt_instances.prev) {
    - if (sb->s_type->fs_flags && FS_SINGLE)
    + if (sb->s_type->fs_flags & FS_SINGLE)
                             put_filesystem(sb->s_type);
                     mntput(mnt);
                     remove_vfsmnt(mnt);

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.rutgers.edu
    Please read the FAQ at http://www.tux.org/lkml/



    This archive was generated by hypermail 2b29 : Tue May 09 2000 - 17:38:06 EDT