aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTyler Hicks <tyhicks@linux.vnet.ibm.com>2010-03-22 01:41:35 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-04-26 10:48:01 -0400
commit8371038fa54c8051c6624560f3777e629b9eef68 (patch)
tree4519fc9e9c34b1d16a4db4e6dfd4c885cd33b211
parent0766ff5226c060424f7d5d6f9e5904b22879b389 (diff)
eCryptfs: Decrypt symlink target for stat size
commit 3a60a1686f0d51c99bd0df8ac93050fb6dfce647 upstream. Create a getattr handler for eCryptfs symlinks that is capable of reading the lower target and decrypting its path. Prior to this patch, a stat's st_size field would represent the strlen of the encrypted path, while readlink() would return the strlen of the decrypted path. This could lead to confusion in some userspace applications, since the two values should be equal. https://bugs.launchpad.net/bugs/524919 Reported-by: Loïc Minier <loic.minier@canonical.com> Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--fs/ecryptfs/inode.c100
1 files changed, 52 insertions, 48 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 4a430ab4115c..0b12c99c6b89 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -647,38 +647,17 @@ out_lock:
647 return rc; 647 return rc;
648} 648}
649 649
650static int 650static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf,
651ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) 651 size_t *bufsiz)
652{ 652{
653 struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
653 char *lower_buf; 654 char *lower_buf;
654 size_t lower_bufsiz; 655 size_t lower_bufsiz = PATH_MAX;
655 struct dentry *lower_dentry;
656 struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
657 char *plaintext_name;
658 size_t plaintext_name_size;
659 mm_segment_t old_fs; 656 mm_segment_t old_fs;
660 int rc; 657 int rc;
661 658
662 lower_dentry = ecryptfs_dentry_to_lower(dentry);
663 if (!lower_dentry->d_inode->i_op->readlink) {
664 rc = -EINVAL;
665 goto out;
666 }
667 mount_crypt_stat = &ecryptfs_superblock_to_private(
668 dentry->d_sb)->mount_crypt_stat;
669 /*
670 * If the lower filename is encrypted, it will result in a significantly
671 * longer name. If needed, truncate the name after decode and decrypt.
672 */
673 if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)
674 lower_bufsiz = PATH_MAX;
675 else
676 lower_bufsiz = bufsiz;
677 /* Released in this function */
678 lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL); 659 lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL);
679 if (lower_buf == NULL) { 660 if (!lower_buf) {
680 printk(KERN_ERR "%s: Out of memory whilst attempting to "
681 "kmalloc [%zd] bytes\n", __func__, lower_bufsiz);
682 rc = -ENOMEM; 661 rc = -ENOMEM;
683 goto out; 662 goto out;
684 } 663 }
@@ -688,29 +667,31 @@ ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
688 (char __user *)lower_buf, 667 (char __user *)lower_buf,
689 lower_bufsiz); 668 lower_bufsiz);
690 set_fs(old_fs); 669 set_fs(old_fs);
691 if (rc >= 0) { 670 if (rc < 0)
692 rc = ecryptfs_decode_and_decrypt_filename(&plaintext_name, 671 goto out;
693 &plaintext_name_size, 672 lower_bufsiz = rc;
694 dentry, lower_buf, 673 rc = ecryptfs_decode_and_decrypt_filename(buf, bufsiz, dentry,
695 rc); 674 lower_buf, lower_bufsiz);
696 if (rc) { 675out:
697 printk(KERN_ERR "%s: Error attempting to decode and "
698 "decrypt filename; rc = [%d]\n", __func__,
699 rc);
700 goto out_free_lower_buf;
701 }
702 /* Check for bufsiz <= 0 done in sys_readlinkat() */
703 rc = copy_to_user(buf, plaintext_name,
704 min((size_t) bufsiz, plaintext_name_size));
705 if (rc)
706 rc = -EFAULT;
707 else
708 rc = plaintext_name_size;
709 kfree(plaintext_name);
710 fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode);
711 }
712out_free_lower_buf:
713 kfree(lower_buf); 676 kfree(lower_buf);
677 return rc;
678}
679
680static int
681ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
682{
683 char *kbuf;
684 size_t kbufsiz, copied;
685 int rc;
686
687 rc = ecryptfs_readlink_lower(dentry, &kbuf, &kbufsiz);
688 if (rc)
689 goto out;
690 copied = min_t(size_t, bufsiz, kbufsiz);
691 rc = copy_to_user(buf, kbuf, copied) ? -EFAULT : copied;
692 kfree(kbuf);
693 fsstack_copy_attr_atime(dentry->d_inode,
694 ecryptfs_dentry_to_lower(dentry)->d_inode);
714out: 695out:
715 return rc; 696 return rc;
716} 697}
@@ -1015,6 +996,28 @@ out:
1015 return rc; 996 return rc;
1016} 997}
1017 998
999int ecryptfs_getattr_link(struct vfsmount *mnt, struct dentry *dentry,
1000 struct kstat *stat)
1001{
1002 struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
1003 int rc = 0;
1004
1005 mount_crypt_stat = &ecryptfs_superblock_to_private(
1006 dentry->d_sb)->mount_crypt_stat;
1007 generic_fillattr(dentry->d_inode, stat);
1008 if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) {
1009 char *target;
1010 size_t targetsiz;
1011
1012 rc = ecryptfs_readlink_lower(dentry, &target, &targetsiz);
1013 if (!rc) {
1014 kfree(target);
1015 stat->size = targetsiz;
1016 }
1017 }
1018 return rc;
1019}
1020
1018int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry, 1021int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
1019 struct kstat *stat) 1022 struct kstat *stat)
1020{ 1023{
@@ -1132,6 +1135,7 @@ const struct inode_operations ecryptfs_symlink_iops = {
1132 .put_link = ecryptfs_put_link, 1135 .put_link = ecryptfs_put_link,
1133 .permission = ecryptfs_permission, 1136 .permission = ecryptfs_permission,
1134 .setattr = ecryptfs_setattr, 1137 .setattr = ecryptfs_setattr,
1138 .getattr = ecryptfs_getattr_link,
1135 .setxattr = ecryptfs_setxattr, 1139 .setxattr = ecryptfs_setxattr,
1136 .getxattr = ecryptfs_getxattr, 1140 .getxattr = ecryptfs_getxattr,
1137 .listxattr = ecryptfs_listxattr, 1141 .listxattr = ecryptfs_listxattr,