aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@redhat.com>2016-12-09 10:45:03 -0500
committerMiklos Szeredi <mszeredi@redhat.com>2016-12-09 10:45:03 -0500
commit6c988f575915ab5162332d61f91dca99dcc17335 (patch)
treec17f5c57209779aca2b1f9845750fa73fa69e0d2
parent3f9ca75516a7e581ff803f751a869c1da5ae5fa5 (diff)
ecryptfs: use vfs_get_link()
Here again we are copying form one buffer to another, while jumping through hoops to make kernel memory look like userspace memory. For no good reason, since vfs_get_link() provides exactly what is needed. As a bonus, now the security hook for readlink is also called on the underlying inode. Note: this can be called from link-following context. But this is okay: - not in RCU mode - commit e54ad7f1ee26 ("proc: prevent stacking filesystems on top") - ecryptfs is *reading* the underlying symlink not following it, so the right security hook is being called Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> Cc: Tyler Hicks <tyhicks@canonical.com>
-rw-r--r--fs/ecryptfs/inode.c29
1 files changed, 12 insertions, 17 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index cf390dceddd2..4ea9d69152dc 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -631,28 +631,23 @@ out_lock:
631 631
632static char *ecryptfs_readlink_lower(struct dentry *dentry, size_t *bufsiz) 632static char *ecryptfs_readlink_lower(struct dentry *dentry, size_t *bufsiz)
633{ 633{
634 DEFINE_DELAYED_CALL(done);
634 struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); 635 struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
635 char *lower_buf; 636 const char *link;
636 char *buf; 637 char *buf;
637 mm_segment_t old_fs;
638 int rc; 638 int rc;
639 639
640 lower_buf = kmalloc(PATH_MAX, GFP_KERNEL); 640 link = vfs_get_link(lower_dentry, &done);
641 if (!lower_buf) 641 if (IS_ERR(link))
642 return ERR_PTR(-ENOMEM); 642 return ERR_CAST(link);
643 old_fs = get_fs(); 643
644 set_fs(get_ds());
645 rc = d_inode(lower_dentry)->i_op->readlink(lower_dentry,
646 (char __user *)lower_buf,
647 PATH_MAX);
648 set_fs(old_fs);
649 if (rc < 0)
650 goto out;
651 rc = ecryptfs_decode_and_decrypt_filename(&buf, bufsiz, dentry->d_sb, 644 rc = ecryptfs_decode_and_decrypt_filename(&buf, bufsiz, dentry->d_sb,
652 lower_buf, rc); 645 link, strlen(link));
653out: 646 do_delayed_call(&done);
654 kfree(lower_buf); 647 if (rc)
655 return rc ? ERR_PTR(rc) : buf; 648 return ERR_PTR(rc);
649
650 return buf;
656} 651}
657 652
658static const char *ecryptfs_get_link(struct dentry *dentry, 653static const char *ecryptfs_get_link(struct dentry *dentry,