From: Arnd Bergmann Date: Wed, 4 Jan 2006 19:31:26 +0000 (+0100) Subject: [PATCH] spufs: dont leak directories in failed spu_create X-Git-Tag: v2.6.16-rc1~666^2~19 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=346f4d3ce948a381a559dcaefb141d79f492335c;p=linux-2.6 [PATCH] spufs: dont leak directories in failed spu_create If get_unused_fd failed in sys_spu_create, we never cleaned up the created directory. Fix that by restructuring the error path. Noticed by Al Viro. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index e314f18ecc..d9a39fb63a 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -251,6 +252,7 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, int mode) d_instantiate(dentry, inode); dget(dentry); dir->i_nlink++; + dentry->d_inode->i_nlink++; goto out; out_free_ctx: @@ -261,18 +263,44 @@ out: return ret; } +static int spufs_context_open(struct dentry *dentry, struct vfsmount *mnt) +{ + int ret; + struct file *filp; + + ret = get_unused_fd(); + if (ret < 0) { + dput(dentry); + mntput(mnt); + goto out; + } + + filp = dentry_open(dentry, mnt, O_RDONLY); + if (IS_ERR(filp)) { + put_unused_fd(ret); + ret = PTR_ERR(filp); + goto out; + } + + filp->f_op = &spufs_context_fops; + fd_install(ret, filp); +out: + return ret; +} + +static struct file_system_type spufs_type; + long spufs_create_thread(struct nameidata *nd, const char *name, unsigned int flags, mode_t mode) { struct dentry *dentry; - struct file *filp; int ret; /* need to be at the root of spufs */ ret = -EINVAL; - if (nd->dentry->d_sb->s_magic != SPUFS_MAGIC || - nd->dentry != nd->dentry->d_sb->s_root) + if (nd->dentry->d_sb->s_type != &spufs_type || + nd->dentry != nd->dentry->d_sb->s_root) goto out; dentry = lookup_create(nd, 1); @@ -289,21 +317,13 @@ spufs_create_thread(struct nameidata *nd, const char *name, if (ret) goto out_dput; - ret = get_unused_fd(); + /* + * get references for dget and mntget, will be released + * in error path of *_open(). + */ + ret = spufs_context_open(dget(dentry), mntget(nd->mnt)); if (ret < 0) - goto out_dput; - - dentry->d_inode->i_nlink++; - - filp = filp_open(name, O_RDONLY, mode); - if (IS_ERR(filp)) { - // FIXME: remove directory again - put_unused_fd(ret); - ret = PTR_ERR(filp); - } else { - filp->f_op = &spufs_context_fops; - fd_install(ret, filp); - } + spufs_rmdir(nd->dentry->d_inode, dentry); out_dput: dput(dentry);