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 - 15:51:37 EST


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 : Mon May 15 2000 - 21:00:14 EST