diff options
Diffstat (limited to 'fs/ecryptfs/inode.c')
-rw-r--r-- | fs/ecryptfs/inode.c | 70 |
1 files changed, 67 insertions, 3 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 1548be26b5e6..e77a2ec71aa5 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -282,7 +282,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, | |||
282 | struct dentry *lower_dentry; | 282 | struct dentry *lower_dentry; |
283 | struct vfsmount *lower_mnt; | 283 | struct vfsmount *lower_mnt; |
284 | char *encoded_name; | 284 | char *encoded_name; |
285 | unsigned int encoded_namelen; | 285 | int encoded_namelen; |
286 | struct ecryptfs_crypt_stat *crypt_stat = NULL; | 286 | struct ecryptfs_crypt_stat *crypt_stat = NULL; |
287 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; | 287 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; |
288 | char *page_virt = NULL; | 288 | char *page_virt = NULL; |
@@ -473,7 +473,7 @@ static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry, | |||
473 | struct dentry *lower_dir_dentry; | 473 | struct dentry *lower_dir_dentry; |
474 | umode_t mode; | 474 | umode_t mode; |
475 | char *encoded_symname; | 475 | char *encoded_symname; |
476 | unsigned int encoded_symlen; | 476 | int encoded_symlen; |
477 | struct ecryptfs_crypt_stat *crypt_stat = NULL; | 477 | struct ecryptfs_crypt_stat *crypt_stat = NULL; |
478 | 478 | ||
479 | lower_dentry = ecryptfs_dentry_to_lower(dentry); | 479 | lower_dentry = ecryptfs_dentry_to_lower(dentry); |
@@ -800,6 +800,25 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) | |||
800 | goto out_fput; | 800 | goto out_fput; |
801 | } | 801 | } |
802 | } else { /* new_length < i_size_read(inode) */ | 802 | } else { /* new_length < i_size_read(inode) */ |
803 | pgoff_t index = 0; | ||
804 | int end_pos_in_page = -1; | ||
805 | |||
806 | if (new_length != 0) { | ||
807 | index = ((new_length - 1) >> PAGE_CACHE_SHIFT); | ||
808 | end_pos_in_page = ((new_length - 1) & ~PAGE_CACHE_MASK); | ||
809 | } | ||
810 | if (end_pos_in_page != (PAGE_CACHE_SIZE - 1)) { | ||
811 | if ((rc = ecryptfs_write_zeros(&fake_ecryptfs_file, | ||
812 | index, | ||
813 | (end_pos_in_page + 1), | ||
814 | ((PAGE_CACHE_SIZE - 1) | ||
815 | - end_pos_in_page)))) { | ||
816 | printk(KERN_ERR "Error attempting to zero out " | ||
817 | "the remainder of the end page on " | ||
818 | "reducing truncate; rc = [%d]\n", rc); | ||
819 | goto out_fput; | ||
820 | } | ||
821 | } | ||
803 | vmtruncate(inode, new_length); | 822 | vmtruncate(inode, new_length); |
804 | rc = ecryptfs_write_inode_size_to_metadata( | 823 | rc = ecryptfs_write_inode_size_to_metadata( |
805 | lower_file, lower_dentry->d_inode, inode, dentry, | 824 | lower_file, lower_dentry->d_inode, inode, dentry, |
@@ -875,9 +894,54 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) | |||
875 | struct ecryptfs_crypt_stat *crypt_stat; | 894 | struct ecryptfs_crypt_stat *crypt_stat; |
876 | 895 | ||
877 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; | 896 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; |
878 | lower_dentry = ecryptfs_dentry_to_lower(dentry); | 897 | if (!(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED)) |
898 | ecryptfs_init_crypt_stat(crypt_stat); | ||
879 | inode = dentry->d_inode; | 899 | inode = dentry->d_inode; |
880 | lower_inode = ecryptfs_inode_to_lower(inode); | 900 | lower_inode = ecryptfs_inode_to_lower(inode); |
901 | lower_dentry = ecryptfs_dentry_to_lower(dentry); | ||
902 | mutex_lock(&crypt_stat->cs_mutex); | ||
903 | if (S_ISDIR(dentry->d_inode->i_mode)) | ||
904 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); | ||
905 | else if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED) | ||
906 | || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { | ||
907 | struct vfsmount *lower_mnt; | ||
908 | struct file *lower_file = NULL; | ||
909 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; | ||
910 | int lower_flags; | ||
911 | |||
912 | lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); | ||
913 | lower_flags = O_RDONLY; | ||
914 | if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, | ||
915 | lower_mnt, lower_flags))) { | ||
916 | printk(KERN_ERR | ||
917 | "Error opening lower file; rc = [%d]\n", rc); | ||
918 | mutex_unlock(&crypt_stat->cs_mutex); | ||
919 | goto out; | ||
920 | } | ||
921 | mount_crypt_stat = &ecryptfs_superblock_to_private( | ||
922 | dentry->d_sb)->mount_crypt_stat; | ||
923 | if ((rc = ecryptfs_read_metadata(dentry, lower_file))) { | ||
924 | if (!(mount_crypt_stat->flags | ||
925 | & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { | ||
926 | rc = -EIO; | ||
927 | printk(KERN_WARNING "Attempt to read file that " | ||
928 | "is not in a valid eCryptfs format, " | ||
929 | "and plaintext passthrough mode is not " | ||
930 | "enabled; returning -EIO\n"); | ||
931 | |||
932 | mutex_unlock(&crypt_stat->cs_mutex); | ||
933 | fput(lower_file); | ||
934 | goto out; | ||
935 | } | ||
936 | rc = 0; | ||
937 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); | ||
938 | mutex_unlock(&crypt_stat->cs_mutex); | ||
939 | fput(lower_file); | ||
940 | goto out; | ||
941 | } | ||
942 | fput(lower_file); | ||
943 | } | ||
944 | mutex_unlock(&crypt_stat->cs_mutex); | ||
881 | if (ia->ia_valid & ATTR_SIZE) { | 945 | if (ia->ia_valid & ATTR_SIZE) { |
882 | ecryptfs_printk(KERN_DEBUG, | 946 | ecryptfs_printk(KERN_DEBUG, |
883 | "ia->ia_valid = [0x%x] ATTR_SIZE" " = [0x%x]\n", | 947 | "ia->ia_valid = [0x%x] ATTR_SIZE" " = [0x%x]\n", |