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 648 return rc; 649 649 } 650 650 651 - static int 652 - ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) 651 + static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf, 652 + size_t *bufsiz) 653 653 { 654 + struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); 654 655 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; 656 + size_t lower_bufsiz = PATH_MAX; 660 657 mm_segment_t old_fs; 661 658 int rc; 662 659 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 660 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); 661 + if (!lower_buf) { 683 662 rc = -ENOMEM; 684 663 goto out; 685 664 } ··· 668 689 (char __user *)lower_buf, 669 690 lower_bufsiz); 670 691 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: 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: 693 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); 694 717 out: 695 718 return rc; 696 719 } ··· 997 1016 return rc; 998 1017 } 999 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 + 1000 1041 int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry, 1001 1042 struct kstat *stat) 1002 1043 { ··· 1136 1133 .put_link = ecryptfs_put_link, 1137 1134 .permission = ecryptfs_permission, 1138 1135 .setattr = ecryptfs_setattr, 1136 + .getattr = ecryptfs_getattr_link, 1139 1137 .setxattr = ecryptfs_setxattr, 1140 1138 .getxattr = ecryptfs_getxattr, 1141 1139 .listxattr = ecryptfs_listxattr,