forked from Minki/linux
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>
This commit is contained in:
parent
ca8e34f2b0
commit
3a6b42cadc
@ -640,8 +640,9 @@ static int
|
||||
ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
|
||||
{
|
||||
char *lower_buf;
|
||||
size_t lower_bufsiz;
|
||||
struct dentry *lower_dentry;
|
||||
struct ecryptfs_crypt_stat *crypt_stat;
|
||||
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
|
||||
char *plaintext_name;
|
||||
size_t plaintext_name_size;
|
||||
mm_segment_t old_fs;
|
||||
@ -652,12 +653,21 @@ ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
|
||||
mount_crypt_stat = &ecryptfs_superblock_to_private(
|
||||
dentry->d_sb)->mount_crypt_stat;
|
||||
/*
|
||||
* If the lower filename is encrypted, it will result in a significantly
|
||||
* longer name. If needed, truncate the name after decode and decrypt.
|
||||
*/
|
||||
if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)
|
||||
lower_bufsiz = PATH_MAX;
|
||||
else
|
||||
lower_bufsiz = bufsiz;
|
||||
/* Released in this function */
|
||||
lower_buf = kmalloc(bufsiz, GFP_KERNEL);
|
||||
lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL);
|
||||
if (lower_buf == NULL) {
|
||||
printk(KERN_ERR "%s: Out of memory whilst attempting to "
|
||||
"kmalloc [%d] bytes\n", __func__, bufsiz);
|
||||
"kmalloc [%d] bytes\n", __func__, lower_bufsiz);
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
@ -665,7 +675,7 @@ ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
|
||||
set_fs(get_ds());
|
||||
rc = lower_dentry->d_inode->i_op->readlink(lower_dentry,
|
||||
(char __user *)lower_buf,
|
||||
bufsiz);
|
||||
lower_bufsiz);
|
||||
set_fs(old_fs);
|
||||
if (rc >= 0) {
|
||||
rc = ecryptfs_decode_and_decrypt_filename(&plaintext_name,
|
||||
@ -678,7 +688,9 @@ ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
|
||||
rc);
|
||||
goto out_free_lower_buf;
|
||||
}
|
||||
rc = copy_to_user(buf, plaintext_name, plaintext_name_size);
|
||||
/* Check for bufsiz <= 0 done in sys_readlinkat() */
|
||||
rc = copy_to_user(buf, plaintext_name,
|
||||
min((unsigned) bufsiz, plaintext_name_size));
|
||||
if (rc)
|
||||
rc = -EFAULT;
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user