aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2013-11-29 22:51:47 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2014-01-25 03:13:00 -0500
commitb22e8fedc19588864a6ba0acefbbed06f05ba713 (patch)
treedb6badfb305598e47a867f399fe30ec38c304cb6 /fs/ecryptfs
parentd8ec26d7f8287f5788a494f56e8814210f0e64be (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.c29
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
662static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf, 662static 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);
685out: 683out:
686 kfree(lower_buf); 684 kfree(lower_buf);
687 return rc; 685 return rc ? ERR_PTR(rc) : buf;
688} 686}
689 687
690static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd) 688static 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;