aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ecryptfs')
-rw-r--r--fs/ecryptfs/inode.c100
1 files changed, 52 insertions, 48 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index ddbd096c740..605f514f3b4 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -648,38 +648,17 @@ out_lock:
648 return rc; 648 return rc;
649} 649}
650 650
651static int 651static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf,
652ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) 652 size_t *bufsiz)
653{ 653{
654 struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
654 char *lower_buf; 655 char *lower_buf;
655 size_t lower_bufsiz; 656 size_t lower_bufsiz = PATH_MAX;
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; 657 mm_segment_t old_fs;
661 int rc; 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 lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL); 660 lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL);
680 if (lower_buf == NULL) { 661 if (!lower_buf) {
681 printk(KERN_ERR "%s: Out of memory whilst attempting to "
682 "kmalloc [%zd] bytes\n", __func__, lower_bufsiz);
683 rc = -ENOMEM; 662 rc = -ENOMEM;
684 goto out; 663 goto out;
685 } 664 }
@@ -689,29 +668,31 @@ ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
689 (char __user *)lower_buf, 668 (char __user *)lower_buf,
690 lower_bufsiz); 669 lower_bufsiz);
691 set_fs(old_fs); 670 set_fs(old_fs);
692 if (rc >= 0) { 671 if (rc < 0)
693 rc = ecryptfs_decode_and_decrypt_filename(&plaintext_name, 672 goto out;
694 &plaintext_name_size, 673 lower_bufsiz = rc;
695 dentry, lower_buf, 674 rc = ecryptfs_decode_and_decrypt_filename(buf, bufsiz, dentry,
696 rc); 675 lower_buf, lower_bufsiz);
697 if (rc) { 676out:
698 printk(KERN_ERR "%s: Error attempting to decode and "
699 "decrypt filename; rc = [%d]\n", __func__,
700 rc);
701 goto out_free_lower_buf;
702 }
703 /* Check for bufsiz <= 0 done in sys_readlinkat() */
704 rc = copy_to_user(buf, plaintext_name,
705 min((size_t) bufsiz, plaintext_name_size));
706 if (rc)
707 rc = -EFAULT;
708 else
709 rc = plaintext_name_size;
710 kfree(plaintext_name);
711 fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode);
712 }
713out_free_lower_buf:
714 kfree(lower_buf); 677 kfree(lower_buf);
678 return rc;
679}
680
681static int
682ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
683{
684 char *kbuf;
685 size_t kbufsiz, copied;
686 int rc;
687
688 rc = ecryptfs_readlink_lower(dentry, &kbuf, &kbufsiz);
689 if (rc)
690 goto out;
691 copied = min_t(size_t, bufsiz, kbufsiz);
692 rc = copy_to_user(buf, kbuf, copied) ? -EFAULT : copied;
693 kfree(kbuf);
694 fsstack_copy_attr_atime(dentry->d_inode,
695 ecryptfs_dentry_to_lower(dentry)->d_inode);
715out: 696out:
716 return rc; 697 return rc;
717} 698}
@@ -1016,6 +997,28 @@ out:
1016 return rc; 997 return rc;
1017} 998}
1018 999
1000int ecryptfs_getattr_link(struct vfsmount *mnt, struct dentry *dentry,
1001 struct kstat *stat)
1002{
1003 struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
1004 int rc = 0;
1005
1006 mount_crypt_stat = &ecryptfs_superblock_to_private(
1007 dentry->d_sb)->mount_crypt_stat;
1008 generic_fillattr(dentry->d_inode, stat);
1009 if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) {
1010 char *target;
1011 size_t targetsiz;
1012
1013 rc = ecryptfs_readlink_lower(dentry, &target, &targetsiz);
1014 if (!rc) {
1015 kfree(target);
1016 stat->size = targetsiz;
1017 }
1018 }
1019 return rc;
1020}
1021
1019int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry, 1022int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
1020 struct kstat *stat) 1023 struct kstat *stat)
1021{ 1024{
@@ -1133,6 +1136,7 @@ const struct inode_operations ecryptfs_symlink_iops = {
1133 .put_link = ecryptfs_put_link, 1136 .put_link = ecryptfs_put_link,
1134 .permission = ecryptfs_permission, 1137 .permission = ecryptfs_permission,
1135 .setattr = ecryptfs_setattr, 1138 .setattr = ecryptfs_setattr,
1139 .getattr = ecryptfs_getattr_link,
1136 .setxattr = ecryptfs_setxattr, 1140 .setxattr = ecryptfs_setxattr,
1137 .getxattr = ecryptfs_getxattr, 1141 .getxattr = ecryptfs_getxattr,
1138 .listxattr = ecryptfs_listxattr, 1142 .listxattr = ecryptfs_listxattr,