eCryptfs: Decrypt symlink target for stat size

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>
Cc: stable@kernel.org
Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>

+52 -48
+52 -48
fs/ecryptfs/inode.c
··· 648 return rc; 649 } 650 651 - static int 652 - ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) 653 { 654 char *lower_buf; 655 - size_t lower_bufsiz; 656 - struct dentry *lower_dentry; 657 - struct ecryptfs_mount_crypt_stat *mount_crypt_stat; 658 - char *plaintext_name; 659 - size_t plaintext_name_size; 660 mm_segment_t old_fs; 661 int rc; 662 663 - lower_dentry = ecryptfs_dentry_to_lower(dentry); 664 - if (!lower_dentry->d_inode->i_op->readlink) { 665 - rc = -EINVAL; 666 - goto out; 667 - } 668 - mount_crypt_stat = &ecryptfs_superblock_to_private( 669 - dentry->d_sb)->mount_crypt_stat; 670 - /* 671 - * If the lower filename is encrypted, it will result in a significantly 672 - * longer name. If needed, truncate the name after decode and decrypt. 673 - */ 674 - if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) 675 - lower_bufsiz = PATH_MAX; 676 - else 677 - lower_bufsiz = bufsiz; 678 - /* Released in this function */ 679 lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL); 680 - if (lower_buf == NULL) { 681 - printk(KERN_ERR "%s: Out of memory whilst attempting to " 682 - "kmalloc [%zd] bytes\n", __func__, lower_bufsiz); 683 rc = -ENOMEM; 684 goto out; 685 } ··· 668 (char __user *)lower_buf, 669 lower_bufsiz); 670 set_fs(old_fs); 671 - if (rc >= 0) { 672 - rc = ecryptfs_decode_and_decrypt_filename(&plaintext_name, 673 - &plaintext_name_size, 674 - dentry, lower_buf, 675 - rc); 676 - if (rc) { 677 - printk(KERN_ERR "%s: Error attempting to decode and " 678 - "decrypt filename; rc = [%d]\n", __func__, 679 - rc); 680 - goto out_free_lower_buf; 681 - } 682 - /* Check for bufsiz <= 0 done in sys_readlinkat() */ 683 - rc = copy_to_user(buf, plaintext_name, 684 - min((size_t) bufsiz, plaintext_name_size)); 685 - if (rc) 686 - rc = -EFAULT; 687 - else 688 - rc = plaintext_name_size; 689 - kfree(plaintext_name); 690 - fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode); 691 - } 692 - out_free_lower_buf: 693 kfree(lower_buf); 694 out: 695 return rc; 696 } ··· 997 return rc; 998 } 999 1000 int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry, 1001 struct kstat *stat) 1002 { ··· 1136 .put_link = ecryptfs_put_link, 1137 .permission = ecryptfs_permission, 1138 .setattr = ecryptfs_setattr, 1139 .setxattr = ecryptfs_setxattr, 1140 .getxattr = ecryptfs_getxattr, 1141 .listxattr = ecryptfs_listxattr,
··· 648 return rc; 649 } 650 651 + static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf, 652 + size_t *bufsiz) 653 { 654 + struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); 655 char *lower_buf; 656 + size_t lower_bufsiz = PATH_MAX; 657 mm_segment_t old_fs; 658 int rc; 659 660 lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL); 661 + if (!lower_buf) { 662 rc = -ENOMEM; 663 goto out; 664 } ··· 689 (char __user *)lower_buf, 690 lower_bufsiz); 691 set_fs(old_fs); 692 + if (rc < 0) 693 + goto out; 694 + lower_bufsiz = rc; 695 + rc = ecryptfs_decode_and_decrypt_filename(buf, bufsiz, dentry, 696 + lower_buf, lower_bufsiz); 697 + out: 698 kfree(lower_buf); 699 + return rc; 700 + } 701 + 702 + static int 703 + ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) 704 + { 705 + char *kbuf; 706 + size_t kbufsiz, copied; 707 + int rc; 708 + 709 + rc = ecryptfs_readlink_lower(dentry, &kbuf, &kbufsiz); 710 + if (rc) 711 + goto out; 712 + copied = min_t(size_t, bufsiz, kbufsiz); 713 + rc = copy_to_user(buf, kbuf, copied) ? -EFAULT : copied; 714 + kfree(kbuf); 715 + fsstack_copy_attr_atime(dentry->d_inode, 716 + ecryptfs_dentry_to_lower(dentry)->d_inode); 717 out: 718 return rc; 719 } ··· 1016 return rc; 1017 } 1018 1019 + int ecryptfs_getattr_link(struct vfsmount *mnt, struct dentry *dentry, 1020 + struct kstat *stat) 1021 + { 1022 + struct ecryptfs_mount_crypt_stat *mount_crypt_stat; 1023 + int rc = 0; 1024 + 1025 + mount_crypt_stat = &ecryptfs_superblock_to_private( 1026 + dentry->d_sb)->mount_crypt_stat; 1027 + generic_fillattr(dentry->d_inode, stat); 1028 + if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) { 1029 + char *target; 1030 + size_t targetsiz; 1031 + 1032 + rc = ecryptfs_readlink_lower(dentry, &target, &targetsiz); 1033 + if (!rc) { 1034 + kfree(target); 1035 + stat->size = targetsiz; 1036 + } 1037 + } 1038 + return rc; 1039 + } 1040 + 1041 int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry, 1042 struct kstat *stat) 1043 { ··· 1133 .put_link = ecryptfs_put_link, 1134 .permission = ecryptfs_permission, 1135 .setattr = ecryptfs_setattr, 1136 + .getattr = ecryptfs_getattr_link, 1137 .setxattr = ecryptfs_setxattr, 1138 .getxattr = ecryptfs_getxattr, 1139 .listxattr = ecryptfs_listxattr,