diff options
Diffstat (limited to 'fs/ecryptfs/inode.c')
-rw-r--r-- | fs/ecryptfs/inode.c | 288 |
1 files changed, 177 insertions, 111 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 429ca0b3ba08..e2d4418affac 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/mount.h> | 31 | #include <linux/mount.h> |
32 | #include <linux/crypto.h> | 32 | #include <linux/crypto.h> |
33 | #include <linux/fs_stack.h> | 33 | #include <linux/fs_stack.h> |
34 | #include <linux/slab.h> | ||
34 | #include <asm/unaligned.h> | 35 | #include <asm/unaligned.h> |
35 | #include "ecryptfs_kernel.h" | 36 | #include "ecryptfs_kernel.h" |
36 | 37 | ||
@@ -282,7 +283,8 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | |||
282 | goto out; | 283 | goto out; |
283 | } | 284 | } |
284 | rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry, | 285 | rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry, |
285 | ecryptfs_dir_inode->i_sb, 1); | 286 | ecryptfs_dir_inode->i_sb, |
287 | ECRYPTFS_INTERPOSE_FLAG_D_ADD); | ||
286 | if (rc) { | 288 | if (rc) { |
287 | printk(KERN_ERR "%s: Error interposing; rc = [%d]\n", | 289 | printk(KERN_ERR "%s: Error interposing; rc = [%d]\n", |
288 | __func__, rc); | 290 | __func__, rc); |
@@ -322,6 +324,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | |||
322 | rc = ecryptfs_read_and_validate_header_region(page_virt, | 324 | rc = ecryptfs_read_and_validate_header_region(page_virt, |
323 | ecryptfs_dentry->d_inode); | 325 | ecryptfs_dentry->d_inode); |
324 | if (rc) { | 326 | if (rc) { |
327 | memset(page_virt, 0, PAGE_CACHE_SIZE); | ||
325 | rc = ecryptfs_read_and_validate_xattr_region(page_virt, | 328 | rc = ecryptfs_read_and_validate_xattr_region(page_virt, |
326 | ecryptfs_dentry); | 329 | ecryptfs_dentry); |
327 | if (rc) { | 330 | if (rc) { |
@@ -334,7 +337,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | |||
334 | ecryptfs_dentry->d_sb)->mount_crypt_stat; | 337 | ecryptfs_dentry->d_sb)->mount_crypt_stat; |
335 | if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { | 338 | if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { |
336 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) | 339 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) |
337 | file_size = (crypt_stat->num_header_bytes_at_front | 340 | file_size = (crypt_stat->metadata_size |
338 | + i_size_read(lower_dentry->d_inode)); | 341 | + i_size_read(lower_dentry->d_inode)); |
339 | else | 342 | else |
340 | file_size = i_size_read(lower_dentry->d_inode); | 343 | file_size = i_size_read(lower_dentry->d_inode); |
@@ -386,9 +389,9 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
386 | mutex_unlock(&lower_dir_dentry->d_inode->i_mutex); | 389 | mutex_unlock(&lower_dir_dentry->d_inode->i_mutex); |
387 | if (IS_ERR(lower_dentry)) { | 390 | if (IS_ERR(lower_dentry)) { |
388 | rc = PTR_ERR(lower_dentry); | 391 | rc = PTR_ERR(lower_dentry); |
389 | printk(KERN_ERR "%s: lookup_one_len() returned [%d] on " | 392 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " |
390 | "lower_dentry = [%s]\n", __func__, rc, | 393 | "[%d] on lower_dentry = [%s]\n", __func__, rc, |
391 | ecryptfs_dentry->d_name.name); | 394 | encrypted_and_encoded_name); |
392 | goto out_d_drop; | 395 | goto out_d_drop; |
393 | } | 396 | } |
394 | if (lower_dentry->d_inode) | 397 | if (lower_dentry->d_inode) |
@@ -415,9 +418,9 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
415 | mutex_unlock(&lower_dir_dentry->d_inode->i_mutex); | 418 | mutex_unlock(&lower_dir_dentry->d_inode->i_mutex); |
416 | if (IS_ERR(lower_dentry)) { | 419 | if (IS_ERR(lower_dentry)) { |
417 | rc = PTR_ERR(lower_dentry); | 420 | rc = PTR_ERR(lower_dentry); |
418 | printk(KERN_ERR "%s: lookup_one_len() returned [%d] on " | 421 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " |
419 | "lower_dentry = [%s]\n", __func__, rc, | 422 | "[%d] on lower_dentry = [%s]\n", __func__, rc, |
420 | encrypted_and_encoded_name); | 423 | encrypted_and_encoded_name); |
421 | goto out_d_drop; | 424 | goto out_d_drop; |
422 | } | 425 | } |
423 | lookup_and_interpose: | 426 | lookup_and_interpose: |
@@ -454,8 +457,8 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir, | |||
454 | rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0); | 457 | rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0); |
455 | if (rc) | 458 | if (rc) |
456 | goto out_lock; | 459 | goto out_lock; |
457 | fsstack_copy_attr_times(dir, lower_new_dentry->d_inode); | 460 | fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); |
458 | fsstack_copy_inode_size(dir, lower_new_dentry->d_inode); | 461 | fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode); |
459 | old_dentry->d_inode->i_nlink = | 462 | old_dentry->d_inode->i_nlink = |
460 | ecryptfs_inode_to_lower(old_dentry->d_inode)->i_nlink; | 463 | ecryptfs_inode_to_lower(old_dentry->d_inode)->i_nlink; |
461 | i_size_write(new_dentry->d_inode, file_size_save); | 464 | i_size_write(new_dentry->d_inode, file_size_save); |
@@ -463,9 +466,6 @@ out_lock: | |||
463 | unlock_dir(lower_dir_dentry); | 466 | unlock_dir(lower_dir_dentry); |
464 | dput(lower_new_dentry); | 467 | dput(lower_new_dentry); |
465 | dput(lower_old_dentry); | 468 | dput(lower_old_dentry); |
466 | d_drop(lower_old_dentry); | ||
467 | d_drop(new_dentry); | ||
468 | d_drop(old_dentry); | ||
469 | return rc; | 469 | return rc; |
470 | } | 470 | } |
471 | 471 | ||
@@ -614,6 +614,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
614 | struct dentry *lower_new_dentry; | 614 | struct dentry *lower_new_dentry; |
615 | struct dentry *lower_old_dir_dentry; | 615 | struct dentry *lower_old_dir_dentry; |
616 | struct dentry *lower_new_dir_dentry; | 616 | struct dentry *lower_new_dir_dentry; |
617 | struct dentry *trap = NULL; | ||
617 | 618 | ||
618 | lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry); | 619 | lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry); |
619 | lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); | 620 | lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); |
@@ -621,7 +622,17 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
621 | dget(lower_new_dentry); | 622 | dget(lower_new_dentry); |
622 | lower_old_dir_dentry = dget_parent(lower_old_dentry); | 623 | lower_old_dir_dentry = dget_parent(lower_old_dentry); |
623 | lower_new_dir_dentry = dget_parent(lower_new_dentry); | 624 | lower_new_dir_dentry = dget_parent(lower_new_dentry); |
624 | lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); | 625 | trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); |
626 | /* source should not be ancestor of target */ | ||
627 | if (trap == lower_old_dentry) { | ||
628 | rc = -EINVAL; | ||
629 | goto out_lock; | ||
630 | } | ||
631 | /* target should not be ancestor of source */ | ||
632 | if (trap == lower_new_dentry) { | ||
633 | rc = -ENOTEMPTY; | ||
634 | goto out_lock; | ||
635 | } | ||
625 | rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry, | 636 | rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry, |
626 | lower_new_dir_dentry->d_inode, lower_new_dentry); | 637 | lower_new_dir_dentry->d_inode, lower_new_dentry); |
627 | if (rc) | 638 | if (rc) |
@@ -638,38 +649,17 @@ out_lock: | |||
638 | return rc; | 649 | return rc; |
639 | } | 650 | } |
640 | 651 | ||
641 | static int | 652 | static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf, |
642 | ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) | 653 | size_t *bufsiz) |
643 | { | 654 | { |
655 | struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); | ||
644 | char *lower_buf; | 656 | char *lower_buf; |
645 | size_t lower_bufsiz; | 657 | size_t lower_bufsiz = PATH_MAX; |
646 | struct dentry *lower_dentry; | ||
647 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; | ||
648 | char *plaintext_name; | ||
649 | size_t plaintext_name_size; | ||
650 | mm_segment_t old_fs; | 658 | mm_segment_t old_fs; |
651 | int rc; | 659 | int rc; |
652 | 660 | ||
653 | lower_dentry = ecryptfs_dentry_to_lower(dentry); | ||
654 | if (!lower_dentry->d_inode->i_op->readlink) { | ||
655 | rc = -EINVAL; | ||
656 | goto out; | ||
657 | } | ||
658 | mount_crypt_stat = &ecryptfs_superblock_to_private( | ||
659 | dentry->d_sb)->mount_crypt_stat; | ||
660 | /* | ||
661 | * If the lower filename is encrypted, it will result in a significantly | ||
662 | * longer name. If needed, truncate the name after decode and decrypt. | ||
663 | */ | ||
664 | if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) | ||
665 | lower_bufsiz = PATH_MAX; | ||
666 | else | ||
667 | lower_bufsiz = bufsiz; | ||
668 | /* Released in this function */ | ||
669 | lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL); | 661 | lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL); |
670 | if (lower_buf == NULL) { | 662 | if (!lower_buf) { |
671 | printk(KERN_ERR "%s: Out of memory whilst attempting to " | ||
672 | "kmalloc [%zd] bytes\n", __func__, lower_bufsiz); | ||
673 | rc = -ENOMEM; | 663 | rc = -ENOMEM; |
674 | goto out; | 664 | goto out; |
675 | } | 665 | } |
@@ -679,29 +669,31 @@ ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) | |||
679 | (char __user *)lower_buf, | 669 | (char __user *)lower_buf, |
680 | lower_bufsiz); | 670 | lower_bufsiz); |
681 | set_fs(old_fs); | 671 | set_fs(old_fs); |
682 | if (rc >= 0) { | 672 | if (rc < 0) |
683 | rc = ecryptfs_decode_and_decrypt_filename(&plaintext_name, | 673 | goto out; |
684 | &plaintext_name_size, | 674 | lower_bufsiz = rc; |
685 | dentry, lower_buf, | 675 | rc = ecryptfs_decode_and_decrypt_filename(buf, bufsiz, dentry, |
686 | rc); | 676 | lower_buf, lower_bufsiz); |
687 | if (rc) { | 677 | out: |
688 | printk(KERN_ERR "%s: Error attempting to decode and " | ||
689 | "decrypt filename; rc = [%d]\n", __func__, | ||
690 | rc); | ||
691 | goto out_free_lower_buf; | ||
692 | } | ||
693 | /* Check for bufsiz <= 0 done in sys_readlinkat() */ | ||
694 | rc = copy_to_user(buf, plaintext_name, | ||
695 | min((size_t) bufsiz, plaintext_name_size)); | ||
696 | if (rc) | ||
697 | rc = -EFAULT; | ||
698 | else | ||
699 | rc = plaintext_name_size; | ||
700 | kfree(plaintext_name); | ||
701 | fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode); | ||
702 | } | ||
703 | out_free_lower_buf: | ||
704 | kfree(lower_buf); | 678 | kfree(lower_buf); |
679 | return rc; | ||
680 | } | ||
681 | |||
682 | static int | ||
683 | ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) | ||
684 | { | ||
685 | char *kbuf; | ||
686 | size_t kbufsiz, copied; | ||
687 | int rc; | ||
688 | |||
689 | rc = ecryptfs_readlink_lower(dentry, &kbuf, &kbufsiz); | ||
690 | if (rc) | ||
691 | goto out; | ||
692 | copied = min_t(size_t, bufsiz, kbufsiz); | ||
693 | rc = copy_to_user(buf, kbuf, copied) ? -EFAULT : copied; | ||
694 | kfree(kbuf); | ||
695 | fsstack_copy_attr_atime(dentry->d_inode, | ||
696 | ecryptfs_dentry_to_lower(dentry)->d_inode); | ||
705 | out: | 697 | out: |
706 | return rc; | 698 | return rc; |
707 | } | 699 | } |
@@ -715,31 +707,31 @@ static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
715 | /* Released in ecryptfs_put_link(); only release here on error */ | 707 | /* Released in ecryptfs_put_link(); only release here on error */ |
716 | buf = kmalloc(len, GFP_KERNEL); | 708 | buf = kmalloc(len, GFP_KERNEL); |
717 | if (!buf) { | 709 | if (!buf) { |
718 | rc = -ENOMEM; | 710 | buf = ERR_PTR(-ENOMEM); |
719 | goto out; | 711 | goto out; |
720 | } | 712 | } |
721 | old_fs = get_fs(); | 713 | old_fs = get_fs(); |
722 | set_fs(get_ds()); | 714 | set_fs(get_ds()); |
723 | rc = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len); | 715 | rc = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len); |
724 | set_fs(old_fs); | 716 | set_fs(old_fs); |
725 | if (rc < 0) | 717 | if (rc < 0) { |
726 | goto out_free; | 718 | kfree(buf); |
727 | else | 719 | buf = ERR_PTR(rc); |
720 | } else | ||
728 | buf[rc] = '\0'; | 721 | buf[rc] = '\0'; |
729 | rc = 0; | ||
730 | nd_set_link(nd, buf); | ||
731 | goto out; | ||
732 | out_free: | ||
733 | kfree(buf); | ||
734 | out: | 722 | out: |
735 | return ERR_PTR(rc); | 723 | nd_set_link(nd, buf); |
724 | return NULL; | ||
736 | } | 725 | } |
737 | 726 | ||
738 | static void | 727 | static void |
739 | ecryptfs_put_link(struct dentry *dentry, struct nameidata *nd, void *ptr) | 728 | ecryptfs_put_link(struct dentry *dentry, struct nameidata *nd, void *ptr) |
740 | { | 729 | { |
741 | /* Free the char* */ | 730 | char *buf = nd_get_link(nd); |
742 | kfree(nd_get_link(nd)); | 731 | if (!IS_ERR(buf)) { |
732 | /* Free the char* */ | ||
733 | kfree(buf); | ||
734 | } | ||
743 | } | 735 | } |
744 | 736 | ||
745 | /** | 737 | /** |
@@ -759,7 +751,7 @@ upper_size_to_lower_size(struct ecryptfs_crypt_stat *crypt_stat, | |||
759 | { | 751 | { |
760 | loff_t lower_size; | 752 | loff_t lower_size; |
761 | 753 | ||
762 | lower_size = crypt_stat->num_header_bytes_at_front; | 754 | lower_size = ecryptfs_lower_header_size(crypt_stat); |
763 | if (upper_size != 0) { | 755 | if (upper_size != 0) { |
764 | loff_t num_extents; | 756 | loff_t num_extents; |
765 | 757 | ||
@@ -772,18 +764,23 @@ upper_size_to_lower_size(struct ecryptfs_crypt_stat *crypt_stat, | |||
772 | } | 764 | } |
773 | 765 | ||
774 | /** | 766 | /** |
775 | * ecryptfs_truncate | 767 | * truncate_upper |
776 | * @dentry: The ecryptfs layer dentry | 768 | * @dentry: The ecryptfs layer dentry |
777 | * @new_length: The length to expand the file to | 769 | * @ia: Address of the ecryptfs inode's attributes |
770 | * @lower_ia: Address of the lower inode's attributes | ||
778 | * | 771 | * |
779 | * Function to handle truncations modifying the size of the file. Note | 772 | * Function to handle truncations modifying the size of the file. Note |
780 | * that the file sizes are interpolated. When expanding, we are simply | 773 | * that the file sizes are interpolated. When expanding, we are simply |
781 | * writing strings of 0's out. When truncating, we need to modify the | 774 | * writing strings of 0's out. When truncating, we truncate the upper |
782 | * underlying file size according to the page index interpolations. | 775 | * inode and update the lower_ia according to the page index |
776 | * interpolations. If ATTR_SIZE is set in lower_ia->ia_valid upon return, | ||
777 | * the caller must use lower_ia in a call to notify_change() to perform | ||
778 | * the truncation of the lower inode. | ||
783 | * | 779 | * |
784 | * Returns zero on success; non-zero otherwise | 780 | * Returns zero on success; non-zero otherwise |
785 | */ | 781 | */ |
786 | int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) | 782 | static int truncate_upper(struct dentry *dentry, struct iattr *ia, |
783 | struct iattr *lower_ia) | ||
787 | { | 784 | { |
788 | int rc = 0; | 785 | int rc = 0; |
789 | struct inode *inode = dentry->d_inode; | 786 | struct inode *inode = dentry->d_inode; |
@@ -794,8 +791,10 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) | |||
794 | loff_t lower_size_before_truncate; | 791 | loff_t lower_size_before_truncate; |
795 | loff_t lower_size_after_truncate; | 792 | loff_t lower_size_after_truncate; |
796 | 793 | ||
797 | if (unlikely((new_length == i_size))) | 794 | if (unlikely((ia->ia_size == i_size))) { |
795 | lower_ia->ia_valid &= ~ATTR_SIZE; | ||
798 | goto out; | 796 | goto out; |
797 | } | ||
799 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; | 798 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; |
800 | /* Set up a fake ecryptfs file, this is used to interface with | 799 | /* Set up a fake ecryptfs file, this is used to interface with |
801 | * the file in the underlying filesystem so that the | 800 | * the file in the underlying filesystem so that the |
@@ -815,28 +814,30 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) | |||
815 | &fake_ecryptfs_file, | 814 | &fake_ecryptfs_file, |
816 | ecryptfs_inode_to_private(dentry->d_inode)->lower_file); | 815 | ecryptfs_inode_to_private(dentry->d_inode)->lower_file); |
817 | /* Switch on growing or shrinking file */ | 816 | /* Switch on growing or shrinking file */ |
818 | if (new_length > i_size) { | 817 | if (ia->ia_size > i_size) { |
819 | char zero[] = { 0x00 }; | 818 | char zero[] = { 0x00 }; |
820 | 819 | ||
820 | lower_ia->ia_valid &= ~ATTR_SIZE; | ||
821 | /* Write a single 0 at the last position of the file; | 821 | /* Write a single 0 at the last position of the file; |
822 | * this triggers code that will fill in 0's throughout | 822 | * this triggers code that will fill in 0's throughout |
823 | * the intermediate portion of the previous end of the | 823 | * the intermediate portion of the previous end of the |
824 | * file and the new and of the file */ | 824 | * file and the new and of the file */ |
825 | rc = ecryptfs_write(&fake_ecryptfs_file, zero, | 825 | rc = ecryptfs_write(&fake_ecryptfs_file, zero, |
826 | (new_length - 1), 1); | 826 | (ia->ia_size - 1), 1); |
827 | } else { /* new_length < i_size_read(inode) */ | 827 | } else { /* ia->ia_size < i_size_read(inode) */ |
828 | /* We're chopping off all the pages down do the page | 828 | /* We're chopping off all the pages down to the page |
829 | * in which new_length is located. Fill in the end of | 829 | * in which ia->ia_size is located. Fill in the end of |
830 | * that page from (new_length & ~PAGE_CACHE_MASK) to | 830 | * that page from (ia->ia_size & ~PAGE_CACHE_MASK) to |
831 | * PAGE_CACHE_SIZE with zeros. */ | 831 | * PAGE_CACHE_SIZE with zeros. */ |
832 | size_t num_zeros = (PAGE_CACHE_SIZE | 832 | size_t num_zeros = (PAGE_CACHE_SIZE |
833 | - (new_length & ~PAGE_CACHE_MASK)); | 833 | - (ia->ia_size & ~PAGE_CACHE_MASK)); |
834 | 834 | ||
835 | if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { | 835 | if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { |
836 | rc = vmtruncate(inode, new_length); | 836 | rc = vmtruncate(inode, ia->ia_size); |
837 | if (rc) | 837 | if (rc) |
838 | goto out_free; | 838 | goto out_free; |
839 | rc = vmtruncate(lower_dentry->d_inode, new_length); | 839 | lower_ia->ia_size = ia->ia_size; |
840 | lower_ia->ia_valid |= ATTR_SIZE; | ||
840 | goto out_free; | 841 | goto out_free; |
841 | } | 842 | } |
842 | if (num_zeros) { | 843 | if (num_zeros) { |
@@ -848,7 +849,7 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) | |||
848 | goto out_free; | 849 | goto out_free; |
849 | } | 850 | } |
850 | rc = ecryptfs_write(&fake_ecryptfs_file, zeros_virt, | 851 | rc = ecryptfs_write(&fake_ecryptfs_file, zeros_virt, |
851 | new_length, num_zeros); | 852 | ia->ia_size, num_zeros); |
852 | kfree(zeros_virt); | 853 | kfree(zeros_virt); |
853 | if (rc) { | 854 | if (rc) { |
854 | printk(KERN_ERR "Error attempting to zero out " | 855 | printk(KERN_ERR "Error attempting to zero out " |
@@ -857,7 +858,7 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) | |||
857 | goto out_free; | 858 | goto out_free; |
858 | } | 859 | } |
859 | } | 860 | } |
860 | vmtruncate(inode, new_length); | 861 | vmtruncate(inode, ia->ia_size); |
861 | rc = ecryptfs_write_inode_size_to_metadata(inode); | 862 | rc = ecryptfs_write_inode_size_to_metadata(inode); |
862 | if (rc) { | 863 | if (rc) { |
863 | printk(KERN_ERR "Problem with " | 864 | printk(KERN_ERR "Problem with " |
@@ -870,10 +871,12 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) | |||
870 | lower_size_before_truncate = | 871 | lower_size_before_truncate = |
871 | upper_size_to_lower_size(crypt_stat, i_size); | 872 | upper_size_to_lower_size(crypt_stat, i_size); |
872 | lower_size_after_truncate = | 873 | lower_size_after_truncate = |
873 | upper_size_to_lower_size(crypt_stat, new_length); | 874 | upper_size_to_lower_size(crypt_stat, ia->ia_size); |
874 | if (lower_size_after_truncate < lower_size_before_truncate) | 875 | if (lower_size_after_truncate < lower_size_before_truncate) { |
875 | vmtruncate(lower_dentry->d_inode, | 876 | lower_ia->ia_size = lower_size_after_truncate; |
876 | lower_size_after_truncate); | 877 | lower_ia->ia_valid |= ATTR_SIZE; |
878 | } else | ||
879 | lower_ia->ia_valid &= ~ATTR_SIZE; | ||
877 | } | 880 | } |
878 | out_free: | 881 | out_free: |
879 | if (ecryptfs_file_to_private(&fake_ecryptfs_file)) | 882 | if (ecryptfs_file_to_private(&fake_ecryptfs_file)) |
@@ -883,6 +886,33 @@ out: | |||
883 | return rc; | 886 | return rc; |
884 | } | 887 | } |
885 | 888 | ||
889 | /** | ||
890 | * ecryptfs_truncate | ||
891 | * @dentry: The ecryptfs layer dentry | ||
892 | * @new_length: The length to expand the file to | ||
893 | * | ||
894 | * Simple function that handles the truncation of an eCryptfs inode and | ||
895 | * its corresponding lower inode. | ||
896 | * | ||
897 | * Returns zero on success; non-zero otherwise | ||
898 | */ | ||
899 | int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) | ||
900 | { | ||
901 | struct iattr ia = { .ia_valid = ATTR_SIZE, .ia_size = new_length }; | ||
902 | struct iattr lower_ia = { .ia_valid = 0 }; | ||
903 | int rc; | ||
904 | |||
905 | rc = truncate_upper(dentry, &ia, &lower_ia); | ||
906 | if (!rc && lower_ia.ia_valid & ATTR_SIZE) { | ||
907 | struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); | ||
908 | |||
909 | mutex_lock(&lower_dentry->d_inode->i_mutex); | ||
910 | rc = notify_change(lower_dentry, &lower_ia); | ||
911 | mutex_unlock(&lower_dentry->d_inode->i_mutex); | ||
912 | } | ||
913 | return rc; | ||
914 | } | ||
915 | |||
886 | static int | 916 | static int |
887 | ecryptfs_permission(struct inode *inode, int mask) | 917 | ecryptfs_permission(struct inode *inode, int mask) |
888 | { | 918 | { |
@@ -905,6 +935,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) | |||
905 | { | 935 | { |
906 | int rc = 0; | 936 | int rc = 0; |
907 | struct dentry *lower_dentry; | 937 | struct dentry *lower_dentry; |
938 | struct iattr lower_ia; | ||
908 | struct inode *inode; | 939 | struct inode *inode; |
909 | struct inode *lower_inode; | 940 | struct inode *lower_inode; |
910 | struct ecryptfs_crypt_stat *crypt_stat; | 941 | struct ecryptfs_crypt_stat *crypt_stat; |
@@ -943,15 +974,11 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) | |||
943 | } | 974 | } |
944 | } | 975 | } |
945 | mutex_unlock(&crypt_stat->cs_mutex); | 976 | mutex_unlock(&crypt_stat->cs_mutex); |
977 | memcpy(&lower_ia, ia, sizeof(lower_ia)); | ||
978 | if (ia->ia_valid & ATTR_FILE) | ||
979 | lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file); | ||
946 | if (ia->ia_valid & ATTR_SIZE) { | 980 | if (ia->ia_valid & ATTR_SIZE) { |
947 | ecryptfs_printk(KERN_DEBUG, | 981 | rc = truncate_upper(dentry, ia, &lower_ia); |
948 | "ia->ia_valid = [0x%x] ATTR_SIZE" " = [0x%x]\n", | ||
949 | ia->ia_valid, ATTR_SIZE); | ||
950 | rc = ecryptfs_truncate(dentry, ia->ia_size); | ||
951 | /* ecryptfs_truncate handles resizing of the lower file */ | ||
952 | ia->ia_valid &= ~ATTR_SIZE; | ||
953 | ecryptfs_printk(KERN_DEBUG, "ia->ia_valid = [%x]\n", | ||
954 | ia->ia_valid); | ||
955 | if (rc < 0) | 982 | if (rc < 0) |
956 | goto out; | 983 | goto out; |
957 | } | 984 | } |
@@ -960,17 +987,54 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) | |||
960 | * mode change is for clearing setuid/setgid bits. Allow lower fs | 987 | * mode change is for clearing setuid/setgid bits. Allow lower fs |
961 | * to interpret this in its own way. | 988 | * to interpret this in its own way. |
962 | */ | 989 | */ |
963 | if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) | 990 | if (lower_ia.ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) |
964 | ia->ia_valid &= ~ATTR_MODE; | 991 | lower_ia.ia_valid &= ~ATTR_MODE; |
965 | 992 | ||
966 | mutex_lock(&lower_dentry->d_inode->i_mutex); | 993 | mutex_lock(&lower_dentry->d_inode->i_mutex); |
967 | rc = notify_change(lower_dentry, ia); | 994 | rc = notify_change(lower_dentry, &lower_ia); |
968 | mutex_unlock(&lower_dentry->d_inode->i_mutex); | 995 | mutex_unlock(&lower_dentry->d_inode->i_mutex); |
969 | out: | 996 | out: |
970 | fsstack_copy_attr_all(inode, lower_inode); | 997 | fsstack_copy_attr_all(inode, lower_inode); |
971 | return rc; | 998 | return rc; |
972 | } | 999 | } |
973 | 1000 | ||
1001 | int ecryptfs_getattr_link(struct vfsmount *mnt, struct dentry *dentry, | ||
1002 | struct kstat *stat) | ||
1003 | { | ||
1004 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; | ||
1005 | int rc = 0; | ||
1006 | |||
1007 | mount_crypt_stat = &ecryptfs_superblock_to_private( | ||
1008 | dentry->d_sb)->mount_crypt_stat; | ||
1009 | generic_fillattr(dentry->d_inode, stat); | ||
1010 | if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) { | ||
1011 | char *target; | ||
1012 | size_t targetsiz; | ||
1013 | |||
1014 | rc = ecryptfs_readlink_lower(dentry, &target, &targetsiz); | ||
1015 | if (!rc) { | ||
1016 | kfree(target); | ||
1017 | stat->size = targetsiz; | ||
1018 | } | ||
1019 | } | ||
1020 | return rc; | ||
1021 | } | ||
1022 | |||
1023 | int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | ||
1024 | struct kstat *stat) | ||
1025 | { | ||
1026 | struct kstat lower_stat; | ||
1027 | int rc; | ||
1028 | |||
1029 | rc = vfs_getattr(ecryptfs_dentry_to_lower_mnt(dentry), | ||
1030 | ecryptfs_dentry_to_lower(dentry), &lower_stat); | ||
1031 | if (!rc) { | ||
1032 | generic_fillattr(dentry->d_inode, stat); | ||
1033 | stat->blocks = lower_stat.blocks; | ||
1034 | } | ||
1035 | return rc; | ||
1036 | } | ||
1037 | |||
974 | int | 1038 | int |
975 | ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, | 1039 | ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, |
976 | size_t size, int flags) | 1040 | size_t size, int flags) |
@@ -980,7 +1044,7 @@ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, | |||
980 | 1044 | ||
981 | lower_dentry = ecryptfs_dentry_to_lower(dentry); | 1045 | lower_dentry = ecryptfs_dentry_to_lower(dentry); |
982 | if (!lower_dentry->d_inode->i_op->setxattr) { | 1046 | if (!lower_dentry->d_inode->i_op->setxattr) { |
983 | rc = -ENOSYS; | 1047 | rc = -EOPNOTSUPP; |
984 | goto out; | 1048 | goto out; |
985 | } | 1049 | } |
986 | mutex_lock(&lower_dentry->d_inode->i_mutex); | 1050 | mutex_lock(&lower_dentry->d_inode->i_mutex); |
@@ -998,7 +1062,7 @@ ecryptfs_getxattr_lower(struct dentry *lower_dentry, const char *name, | |||
998 | int rc = 0; | 1062 | int rc = 0; |
999 | 1063 | ||
1000 | if (!lower_dentry->d_inode->i_op->getxattr) { | 1064 | if (!lower_dentry->d_inode->i_op->getxattr) { |
1001 | rc = -ENOSYS; | 1065 | rc = -EOPNOTSUPP; |
1002 | goto out; | 1066 | goto out; |
1003 | } | 1067 | } |
1004 | mutex_lock(&lower_dentry->d_inode->i_mutex); | 1068 | mutex_lock(&lower_dentry->d_inode->i_mutex); |
@@ -1025,7 +1089,7 @@ ecryptfs_listxattr(struct dentry *dentry, char *list, size_t size) | |||
1025 | 1089 | ||
1026 | lower_dentry = ecryptfs_dentry_to_lower(dentry); | 1090 | lower_dentry = ecryptfs_dentry_to_lower(dentry); |
1027 | if (!lower_dentry->d_inode->i_op->listxattr) { | 1091 | if (!lower_dentry->d_inode->i_op->listxattr) { |
1028 | rc = -ENOSYS; | 1092 | rc = -EOPNOTSUPP; |
1029 | goto out; | 1093 | goto out; |
1030 | } | 1094 | } |
1031 | mutex_lock(&lower_dentry->d_inode->i_mutex); | 1095 | mutex_lock(&lower_dentry->d_inode->i_mutex); |
@@ -1042,7 +1106,7 @@ static int ecryptfs_removexattr(struct dentry *dentry, const char *name) | |||
1042 | 1106 | ||
1043 | lower_dentry = ecryptfs_dentry_to_lower(dentry); | 1107 | lower_dentry = ecryptfs_dentry_to_lower(dentry); |
1044 | if (!lower_dentry->d_inode->i_op->removexattr) { | 1108 | if (!lower_dentry->d_inode->i_op->removexattr) { |
1045 | rc = -ENOSYS; | 1109 | rc = -EOPNOTSUPP; |
1046 | goto out; | 1110 | goto out; |
1047 | } | 1111 | } |
1048 | mutex_lock(&lower_dentry->d_inode->i_mutex); | 1112 | mutex_lock(&lower_dentry->d_inode->i_mutex); |
@@ -1073,6 +1137,7 @@ const struct inode_operations ecryptfs_symlink_iops = { | |||
1073 | .put_link = ecryptfs_put_link, | 1137 | .put_link = ecryptfs_put_link, |
1074 | .permission = ecryptfs_permission, | 1138 | .permission = ecryptfs_permission, |
1075 | .setattr = ecryptfs_setattr, | 1139 | .setattr = ecryptfs_setattr, |
1140 | .getattr = ecryptfs_getattr_link, | ||
1076 | .setxattr = ecryptfs_setxattr, | 1141 | .setxattr = ecryptfs_setxattr, |
1077 | .getxattr = ecryptfs_getxattr, | 1142 | .getxattr = ecryptfs_getxattr, |
1078 | .listxattr = ecryptfs_listxattr, | 1143 | .listxattr = ecryptfs_listxattr, |
@@ -1100,6 +1165,7 @@ const struct inode_operations ecryptfs_dir_iops = { | |||
1100 | const struct inode_operations ecryptfs_main_iops = { | 1165 | const struct inode_operations ecryptfs_main_iops = { |
1101 | .permission = ecryptfs_permission, | 1166 | .permission = ecryptfs_permission, |
1102 | .setattr = ecryptfs_setattr, | 1167 | .setattr = ecryptfs_setattr, |
1168 | .getattr = ecryptfs_getattr, | ||
1103 | .setxattr = ecryptfs_setxattr, | 1169 | .setxattr = ecryptfs_setxattr, |
1104 | .getxattr = ecryptfs_getxattr, | 1170 | .getxattr = ecryptfs_getxattr, |
1105 | .listxattr = ecryptfs_listxattr, | 1171 | .listxattr = ecryptfs_listxattr, |