aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTyler Hicks <tyhicks@linux.vnet.ibm.com>2009-04-16 19:35:37 -0400
committerTyler Hicks <tyhicks@linux.vnet.ibm.com>2009-04-22 18:02:46 -0400
commit3a6b42cadc112b01daf0525e5fcd90bb333a5bb3 (patch)
tree78cd37050a80e5c99eaa3ee97e20af834026c4d1
parentca8e34f2b05a8289b47907b083dc01dd654ecbde (diff)
eCryptfs: Larger buffer for encrypted symlink targets
When using filename encryption with eCryptfs, the value of the symlink in the lower filesystem is encrypted and stored as a Tag 70 packet. This results in a longer symlink target than if the target value wasn't encrypted. Users were reporting these messages in their syslog: [ 45.653441] ecryptfs_parse_tag_70_packet: max_packet_size is [56]; real packet size is [51] [ 45.653444] ecryptfs_decode_and_decrypt_filename: Could not parse tag 70 packet from filename; copying through filename as-is This was due to bufsiz, one the arguments in readlink(), being used to when allocating the buffer passed to the lower inode's readlink(). That symlink target may be very large, but when decoded and decrypted, could end up being smaller than bufsize. To fix this, the buffer passed to the lower inode's readlink() will always be PATH_MAX in size when filename encryption is enabled. Any necessary truncation occurs after the decoding and decrypting. Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
-rw-r--r--fs/ecryptfs/inode.c24
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
640ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) 640ecryptfs_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