diff options
author | OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> | 2010-01-11 13:36:14 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-01-14 09:05:26 -0500 |
commit | 806892e9e12e731a0ca76c8f62ad95cf8eea9614 (patch) | |
tree | a063df1524ed862ef2475052e1cc1c66de390dc2 /fs/ecryptfs/inode.c | |
parent | 6d125529c6cbfe570ce3bf9a0728548f087499da (diff) |
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/inode.c')
-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) | |||
715 | /* Released in ecryptfs_put_link(); only release here on error */ | 715 | /* Released in ecryptfs_put_link(); only release here on error */ |
716 | buf = kmalloc(len, GFP_KERNEL); | 716 | buf = kmalloc(len, GFP_KERNEL); |
717 | if (!buf) { | 717 | if (!buf) { |
718 | rc = -ENOMEM; | 718 | buf = ERR_PTR(-ENOMEM); |
719 | goto out; | 719 | goto out; |
720 | } | 720 | } |
721 | old_fs = get_fs(); | 721 | old_fs = get_fs(); |
722 | set_fs(get_ds()); | 722 | set_fs(get_ds()); |
723 | rc = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len); | 723 | rc = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len); |
724 | set_fs(old_fs); | 724 | set_fs(old_fs); |
725 | if (rc < 0) | 725 | if (rc < 0) { |
726 | goto out_free; | 726 | kfree(buf); |
727 | else | 727 | buf = ERR_PTR(rc); |
728 | } else | ||
728 | buf[rc] = '\0'; | 729 | buf[rc] = '\0'; |
729 | rc = 0; | ||
730 | nd_set_link(nd, buf); | ||
731 | goto out; | ||
732 | out_free: | ||
733 | kfree(buf); | ||
734 | out: | 730 | out: |
735 | return ERR_PTR(rc); | 731 | nd_set_link(nd, buf); |
732 | return NULL; | ||
736 | } | 733 | } |
737 | 734 | ||
738 | static void | 735 | static void |
739 | ecryptfs_put_link(struct dentry *dentry, struct nameidata *nd, void *ptr) | 736 | ecryptfs_put_link(struct dentry *dentry, struct nameidata *nd, void *ptr) |
740 | { | 737 | { |
741 | /* Free the char* */ | 738 | char *buf = nd_get_link(nd); |
742 | kfree(nd_get_link(nd)); | 739 | if (!IS_ERR(buf)) { |
740 | /* Free the char* */ | ||
741 | kfree(buf); | ||
742 | } | ||
743 | } | 743 | } |
744 | 744 | ||
745 | /** | 745 | /** |