diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2013-11-29 22:51:47 -0500 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-01-25 03:13:00 -0500 |
| commit | b22e8fedc19588864a6ba0acefbbed06f05ba713 (patch) | |
| tree | db6badfb305598e47a867f399fe30ec38c304cb6 /fs/ecryptfs | |
| parent | d8ec26d7f8287f5788a494f56e8814210f0e64be (diff) | |
ecryptfs: fix failure handling in ->readlink()
If ecryptfs_readlink_lower() fails, buf remains an uninitialized
pointer and passing it nd_set_link() won't do anything good.
Fixed by switching ecryptfs_readlink_lower() to saner API - make it
return buf or ERR_PTR(...) and update callers.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/ecryptfs')
| -rw-r--r-- | fs/ecryptfs/inode.c | 29 |
1 files changed, 13 insertions, 16 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index c36c44824471..b167ca48b8ee 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
| @@ -659,19 +659,17 @@ out_lock: | |||
| 659 | return rc; | 659 | return rc; |
| 660 | } | 660 | } |
| 661 | 661 | ||
| 662 | static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf, | 662 | static char *ecryptfs_readlink_lower(struct dentry *dentry, size_t *bufsiz) |
| 663 | size_t *bufsiz) | ||
| 664 | { | 663 | { |
| 665 | struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); | 664 | struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); |
| 666 | char *lower_buf; | 665 | char *lower_buf; |
| 666 | char *buf; | ||
| 667 | mm_segment_t old_fs; | 667 | mm_segment_t old_fs; |
| 668 | int rc; | 668 | int rc; |
| 669 | 669 | ||
| 670 | lower_buf = kmalloc(PATH_MAX, GFP_KERNEL); | 670 | lower_buf = kmalloc(PATH_MAX, GFP_KERNEL); |
| 671 | if (!lower_buf) { | 671 | if (!lower_buf) |
| 672 | rc = -ENOMEM; | 672 | return ERR_PTR(-ENOMEM); |
| 673 | goto out; | ||
| 674 | } | ||
| 675 | old_fs = get_fs(); | 673 | old_fs = get_fs(); |
| 676 | set_fs(get_ds()); | 674 | set_fs(get_ds()); |
| 677 | rc = lower_dentry->d_inode->i_op->readlink(lower_dentry, | 675 | rc = lower_dentry->d_inode->i_op->readlink(lower_dentry, |
| @@ -680,21 +678,18 @@ static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf, | |||
| 680 | set_fs(old_fs); | 678 | set_fs(old_fs); |
| 681 | if (rc < 0) | 679 | if (rc < 0) |
| 682 | goto out; | 680 | goto out; |
| 683 | rc = ecryptfs_decode_and_decrypt_filename(buf, bufsiz, dentry->d_sb, | 681 | rc = ecryptfs_decode_and_decrypt_filename(&buf, bufsiz, dentry->d_sb, |
| 684 | lower_buf, rc); | 682 | lower_buf, rc); |
| 685 | out: | 683 | out: |
| 686 | kfree(lower_buf); | 684 | kfree(lower_buf); |
| 687 | return rc; | 685 | return rc ? ERR_PTR(rc) : buf; |
| 688 | } | 686 | } |
| 689 | 687 | ||
| 690 | static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd) | 688 | static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd) |
| 691 | { | 689 | { |
| 692 | char *buf; | 690 | size_t len; |
| 693 | size_t len = PATH_MAX; | 691 | char *buf = ecryptfs_readlink_lower(dentry, &len); |
| 694 | int rc; | 692 | if (IS_ERR(buf)) |
| 695 | |||
| 696 | rc = ecryptfs_readlink_lower(dentry, &buf, &len); | ||
| 697 | if (rc) | ||
| 698 | goto out; | 693 | goto out; |
| 699 | fsstack_copy_attr_atime(dentry->d_inode, | 694 | fsstack_copy_attr_atime(dentry->d_inode, |
| 700 | ecryptfs_dentry_to_lower(dentry)->d_inode); | 695 | ecryptfs_dentry_to_lower(dentry)->d_inode); |
| @@ -1003,10 +998,12 @@ static int ecryptfs_getattr_link(struct vfsmount *mnt, struct dentry *dentry, | |||
| 1003 | char *target; | 998 | char *target; |
| 1004 | size_t targetsiz; | 999 | size_t targetsiz; |
| 1005 | 1000 | ||
| 1006 | rc = ecryptfs_readlink_lower(dentry, &target, &targetsiz); | 1001 | target = ecryptfs_readlink_lower(dentry, &targetsiz); |
| 1007 | if (!rc) { | 1002 | if (!IS_ERR(target)) { |
| 1008 | kfree(target); | 1003 | kfree(target); |
| 1009 | stat->size = targetsiz; | 1004 | stat->size = targetsiz; |
| 1005 | } else { | ||
| 1006 | rc = PTR_ERR(target); | ||
| 1010 | } | 1007 | } |
| 1011 | } | 1008 | } |
| 1012 | return rc; | 1009 | return rc; |
