diff options
Diffstat (limited to 'fs/ecryptfs')
-rw-r--r-- | fs/ecryptfs/inode.c | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index d8325263ba6e..93bc0f8174a7 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -640,8 +640,9 @@ static int | |||
640 | ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) | 640 | ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) |
641 | { | 641 | { |
642 | char *lower_buf; | 642 | char *lower_buf; |
643 | size_t lower_bufsiz; | ||
643 | struct dentry *lower_dentry; | 644 | struct dentry *lower_dentry; |
644 | struct ecryptfs_crypt_stat *crypt_stat; | 645 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; |
645 | char *plaintext_name; | 646 | char *plaintext_name; |
646 | size_t plaintext_name_size; | 647 | size_t plaintext_name_size; |
647 | mm_segment_t old_fs; | 648 | mm_segment_t old_fs; |
@@ -652,12 +653,21 @@ ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) | |||
652 | rc = -EINVAL; | 653 | rc = -EINVAL; |
653 | goto out; | 654 | goto out; |
654 | } | 655 | } |
655 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; | 656 | mount_crypt_stat = &ecryptfs_superblock_to_private( |
657 | dentry->d_sb)->mount_crypt_stat; | ||
658 | /* | ||
659 | * If the lower filename is encrypted, it will result in a significantly | ||
660 | * longer name. If needed, truncate the name after decode and decrypt. | ||
661 | */ | ||
662 | if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) | ||
663 | lower_bufsiz = PATH_MAX; | ||
664 | else | ||
665 | lower_bufsiz = bufsiz; | ||
656 | /* Released in this function */ | 666 | /* Released in this function */ |
657 | lower_buf = kmalloc(bufsiz, GFP_KERNEL); | 667 | lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL); |
658 | if (lower_buf == NULL) { | 668 | if (lower_buf == NULL) { |
659 | printk(KERN_ERR "%s: Out of memory whilst attempting to " | 669 | printk(KERN_ERR "%s: Out of memory whilst attempting to " |
660 | "kmalloc [%d] bytes\n", __func__, bufsiz); | 670 | "kmalloc [%d] bytes\n", __func__, lower_bufsiz); |
661 | rc = -ENOMEM; | 671 | rc = -ENOMEM; |
662 | goto out; | 672 | goto out; |
663 | } | 673 | } |
@@ -665,7 +675,7 @@ ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) | |||
665 | set_fs(get_ds()); | 675 | set_fs(get_ds()); |
666 | rc = lower_dentry->d_inode->i_op->readlink(lower_dentry, | 676 | rc = lower_dentry->d_inode->i_op->readlink(lower_dentry, |
667 | (char __user *)lower_buf, | 677 | (char __user *)lower_buf, |
668 | bufsiz); | 678 | lower_bufsiz); |
669 | set_fs(old_fs); | 679 | set_fs(old_fs); |
670 | if (rc >= 0) { | 680 | if (rc >= 0) { |
671 | rc = ecryptfs_decode_and_decrypt_filename(&plaintext_name, | 681 | rc = ecryptfs_decode_and_decrypt_filename(&plaintext_name, |
@@ -678,7 +688,9 @@ ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) | |||
678 | rc); | 688 | rc); |
679 | goto out_free_lower_buf; | 689 | goto out_free_lower_buf; |
680 | } | 690 | } |
681 | rc = copy_to_user(buf, plaintext_name, plaintext_name_size); | 691 | /* Check for bufsiz <= 0 done in sys_readlinkat() */ |
692 | rc = copy_to_user(buf, plaintext_name, | ||
693 | min((unsigned) bufsiz, plaintext_name_size)); | ||
682 | if (rc) | 694 | if (rc) |
683 | rc = -EFAULT; | 695 | rc = -EFAULT; |
684 | else | 696 | else |