diff options
author | OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> | 2010-01-12 03:36:14 +0900 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-01-14 09:05:26 -0500 |
commit | 806892e9e12e731a0ca76c8f62ad95cf8eea9614 (patch) | |
tree | a063df1524ed862ef2475052e1cc1c66de390dc2 /fs/ecryptfs | |
parent | 6d125529c6cbfe570ce3bf9a0728548f087499da (diff) | |
download | linux-stable-806892e9e12e731a0ca76c8f62ad95cf8eea9614.tar.gz linux-stable-806892e9e12e731a0ca76c8f62ad95cf8eea9614.tar.bz2 linux-stable-806892e9e12e731a0ca76c8f62ad95cf8eea9614.zip |
ecryptfs: Fix refcnt leak on ecryptfs_follow_link() error path
If ->follow_link handler return the error, it should decrement
nd->path refcnt. But, ecryptfs_follow_link() doesn't decrement.
This patch fix it by using usual nd_set_link() style error handling,
instead of playing with nd->path.
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/ecryptfs')
-rw-r--r-- | fs/ecryptfs/inode.c | 24 |
1 files changed, 12 insertions, 12 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 429ca0b3ba08..7f8545032930 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -715,31 +715,31 @@ static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd) /* Released in ecryptfs_put_link(); only release here on error */ buf = kmalloc(len, GFP_KERNEL); if (!buf) { - rc = -ENOMEM; + buf = ERR_PTR(-ENOMEM); goto out; } old_fs = get_fs(); set_fs(get_ds()); rc = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len); set_fs(old_fs); - if (rc < 0) - goto out_free; - else + if (rc < 0) { + kfree(buf); + buf = ERR_PTR(rc); + } else buf[rc] = '\0'; - rc = 0; - nd_set_link(nd, buf); - goto out; -out_free: - kfree(buf); out: - return ERR_PTR(rc); + nd_set_link(nd, buf); + return NULL; } static void ecryptfs_put_link(struct dentry *dentry, struct nameidata *nd, void *ptr) { - /* Free the char* */ - kfree(nd_get_link(nd)); + char *buf = nd_get_link(nd); + if (!IS_ERR(buf)) { + /* Free the char* */ + kfree(buf); + } } /** |