diff options
author | Miklos Szeredi <mszeredi@redhat.com> | 2016-12-09 10:45:03 -0500 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2016-12-09 10:45:03 -0500 |
commit | 6c988f575915ab5162332d61f91dca99dcc17335 (patch) | |
tree | c17f5c57209779aca2b1f9845750fa73fa69e0d2 | |
parent | 3f9ca75516a7e581ff803f751a869c1da5ae5fa5 (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.c | 29 |
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 | ||
632 | static char *ecryptfs_readlink_lower(struct dentry *dentry, size_t *bufsiz) | 632 | static 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)); |
653 | out: | 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 | ||
658 | static const char *ecryptfs_get_link(struct dentry *dentry, | 653 | static const char *ecryptfs_get_link(struct dentry *dentry, |