diff options
Diffstat (limited to 'fs/ecryptfs/inode.c')
-rw-r--r-- | fs/ecryptfs/inode.c | 158 |
1 files changed, 101 insertions, 57 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index e2d4418affac..6c55113e7222 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -142,19 +142,10 @@ out: | |||
142 | static int grow_file(struct dentry *ecryptfs_dentry) | 142 | static int grow_file(struct dentry *ecryptfs_dentry) |
143 | { | 143 | { |
144 | struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode; | 144 | struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode; |
145 | struct file fake_file; | ||
146 | struct ecryptfs_file_info tmp_file_info; | ||
147 | char zero_virt[] = { 0x00 }; | 145 | char zero_virt[] = { 0x00 }; |
148 | int rc = 0; | 146 | int rc = 0; |
149 | 147 | ||
150 | memset(&fake_file, 0, sizeof(fake_file)); | 148 | rc = ecryptfs_write(ecryptfs_inode, zero_virt, 0, 1); |
151 | fake_file.f_path.dentry = ecryptfs_dentry; | ||
152 | memset(&tmp_file_info, 0, sizeof(tmp_file_info)); | ||
153 | ecryptfs_set_file_private(&fake_file, &tmp_file_info); | ||
154 | ecryptfs_set_file_lower( | ||
155 | &fake_file, | ||
156 | ecryptfs_inode_to_private(ecryptfs_inode)->lower_file); | ||
157 | rc = ecryptfs_write(&fake_file, zero_virt, 0, 1); | ||
158 | i_size_write(ecryptfs_inode, 0); | 149 | i_size_write(ecryptfs_inode, 0); |
159 | rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode); | 150 | rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode); |
160 | ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat.flags |= | 151 | ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat.flags |= |
@@ -273,7 +264,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | |||
273 | printk(KERN_ERR "%s: Out of memory whilst attempting " | 264 | printk(KERN_ERR "%s: Out of memory whilst attempting " |
274 | "to allocate ecryptfs_dentry_info struct\n", | 265 | "to allocate ecryptfs_dentry_info struct\n", |
275 | __func__); | 266 | __func__); |
276 | goto out_dput; | 267 | goto out_put; |
277 | } | 268 | } |
278 | ecryptfs_set_dentry_lower(ecryptfs_dentry, lower_dentry); | 269 | ecryptfs_set_dentry_lower(ecryptfs_dentry, lower_dentry); |
279 | ecryptfs_set_dentry_lower_mnt(ecryptfs_dentry, lower_mnt); | 270 | ecryptfs_set_dentry_lower_mnt(ecryptfs_dentry, lower_mnt); |
@@ -348,14 +339,85 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | |||
348 | out_free_kmem: | 339 | out_free_kmem: |
349 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); | 340 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); |
350 | goto out; | 341 | goto out; |
351 | out_dput: | 342 | out_put: |
352 | dput(lower_dentry); | 343 | dput(lower_dentry); |
344 | mntput(lower_mnt); | ||
353 | d_drop(ecryptfs_dentry); | 345 | d_drop(ecryptfs_dentry); |
354 | out: | 346 | out: |
355 | return rc; | 347 | return rc; |
356 | } | 348 | } |
357 | 349 | ||
358 | /** | 350 | /** |
351 | * ecryptfs_new_lower_dentry | ||
352 | * @ename: The name of the new dentry. | ||
353 | * @lower_dir_dentry: Parent directory of the new dentry. | ||
354 | * @nd: nameidata from last lookup. | ||
355 | * | ||
356 | * Create a new dentry or get it from lower parent dir. | ||
357 | */ | ||
358 | static struct dentry * | ||
359 | ecryptfs_new_lower_dentry(struct qstr *name, struct dentry *lower_dir_dentry, | ||
360 | struct nameidata *nd) | ||
361 | { | ||
362 | struct dentry *new_dentry; | ||
363 | struct dentry *tmp; | ||
364 | struct inode *lower_dir_inode; | ||
365 | |||
366 | lower_dir_inode = lower_dir_dentry->d_inode; | ||
367 | |||
368 | tmp = d_alloc(lower_dir_dentry, name); | ||
369 | if (!tmp) | ||
370 | return ERR_PTR(-ENOMEM); | ||
371 | |||
372 | mutex_lock(&lower_dir_inode->i_mutex); | ||
373 | new_dentry = lower_dir_inode->i_op->lookup(lower_dir_inode, tmp, nd); | ||
374 | mutex_unlock(&lower_dir_inode->i_mutex); | ||
375 | |||
376 | if (!new_dentry) | ||
377 | new_dentry = tmp; | ||
378 | else | ||
379 | dput(tmp); | ||
380 | |||
381 | return new_dentry; | ||
382 | } | ||
383 | |||
384 | |||
385 | /** | ||
386 | * ecryptfs_lookup_one_lower | ||
387 | * @ecryptfs_dentry: The eCryptfs dentry that we are looking up | ||
388 | * @lower_dir_dentry: lower parent directory | ||
389 | * | ||
390 | * Get the lower dentry from vfs. If lower dentry does not exist yet, | ||
391 | * create it. | ||
392 | */ | ||
393 | static struct dentry * | ||
394 | ecryptfs_lookup_one_lower(struct dentry *ecryptfs_dentry, | ||
395 | struct dentry *lower_dir_dentry) | ||
396 | { | ||
397 | struct nameidata nd; | ||
398 | struct vfsmount *lower_mnt; | ||
399 | struct qstr *name; | ||
400 | int err; | ||
401 | |||
402 | name = &ecryptfs_dentry->d_name; | ||
403 | lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt( | ||
404 | ecryptfs_dentry->d_parent)); | ||
405 | err = vfs_path_lookup(lower_dir_dentry, lower_mnt, name->name , 0, &nd); | ||
406 | mntput(lower_mnt); | ||
407 | |||
408 | if (!err) { | ||
409 | /* we dont need the mount */ | ||
410 | mntput(nd.path.mnt); | ||
411 | return nd.path.dentry; | ||
412 | } | ||
413 | if (err != -ENOENT) | ||
414 | return ERR_PTR(err); | ||
415 | |||
416 | /* create a new lower dentry */ | ||
417 | return ecryptfs_new_lower_dentry(name, lower_dir_dentry, &nd); | ||
418 | } | ||
419 | |||
420 | /** | ||
359 | * ecryptfs_lookup | 421 | * ecryptfs_lookup |
360 | * @ecryptfs_dir_inode: The eCryptfs directory inode | 422 | * @ecryptfs_dir_inode: The eCryptfs directory inode |
361 | * @ecryptfs_dentry: The eCryptfs dentry that we are looking up | 423 | * @ecryptfs_dentry: The eCryptfs dentry that we are looking up |
@@ -382,14 +444,12 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
382 | goto out_d_drop; | 444 | goto out_d_drop; |
383 | } | 445 | } |
384 | lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent); | 446 | lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent); |
385 | mutex_lock(&lower_dir_dentry->d_inode->i_mutex); | 447 | |
386 | lower_dentry = lookup_one_len(ecryptfs_dentry->d_name.name, | 448 | lower_dentry = ecryptfs_lookup_one_lower(ecryptfs_dentry, |
387 | lower_dir_dentry, | 449 | lower_dir_dentry); |
388 | ecryptfs_dentry->d_name.len); | ||
389 | mutex_unlock(&lower_dir_dentry->d_inode->i_mutex); | ||
390 | if (IS_ERR(lower_dentry)) { | 450 | if (IS_ERR(lower_dentry)) { |
391 | rc = PTR_ERR(lower_dentry); | 451 | rc = PTR_ERR(lower_dentry); |
392 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " | 452 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_lower() returned " |
393 | "[%d] on lower_dentry = [%s]\n", __func__, rc, | 453 | "[%d] on lower_dentry = [%s]\n", __func__, rc, |
394 | encrypted_and_encoded_name); | 454 | encrypted_and_encoded_name); |
395 | goto out_d_drop; | 455 | goto out_d_drop; |
@@ -411,14 +471,11 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
411 | "filename; rc = [%d]\n", __func__, rc); | 471 | "filename; rc = [%d]\n", __func__, rc); |
412 | goto out_d_drop; | 472 | goto out_d_drop; |
413 | } | 473 | } |
414 | mutex_lock(&lower_dir_dentry->d_inode->i_mutex); | 474 | lower_dentry = ecryptfs_lookup_one_lower(ecryptfs_dentry, |
415 | lower_dentry = lookup_one_len(encrypted_and_encoded_name, | 475 | lower_dir_dentry); |
416 | lower_dir_dentry, | ||
417 | encrypted_and_encoded_name_size - 1); | ||
418 | mutex_unlock(&lower_dir_dentry->d_inode->i_mutex); | ||
419 | if (IS_ERR(lower_dentry)) { | 476 | if (IS_ERR(lower_dentry)) { |
420 | rc = PTR_ERR(lower_dentry); | 477 | rc = PTR_ERR(lower_dentry); |
421 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " | 478 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_lower() returned " |
422 | "[%d] on lower_dentry = [%s]\n", __func__, rc, | 479 | "[%d] on lower_dentry = [%s]\n", __func__, rc, |
423 | encrypted_and_encoded_name); | 480 | encrypted_and_encoded_name); |
424 | goto out_d_drop; | 481 | goto out_d_drop; |
@@ -784,8 +841,6 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia, | |||
784 | { | 841 | { |
785 | int rc = 0; | 842 | int rc = 0; |
786 | struct inode *inode = dentry->d_inode; | 843 | struct inode *inode = dentry->d_inode; |
787 | struct dentry *lower_dentry; | ||
788 | struct file fake_ecryptfs_file; | ||
789 | struct ecryptfs_crypt_stat *crypt_stat; | 844 | struct ecryptfs_crypt_stat *crypt_stat; |
790 | loff_t i_size = i_size_read(inode); | 845 | loff_t i_size = i_size_read(inode); |
791 | loff_t lower_size_before_truncate; | 846 | loff_t lower_size_before_truncate; |
@@ -796,23 +851,6 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia, | |||
796 | goto out; | 851 | goto out; |
797 | } | 852 | } |
798 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; | 853 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; |
799 | /* Set up a fake ecryptfs file, this is used to interface with | ||
800 | * the file in the underlying filesystem so that the | ||
801 | * truncation has an effect there as well. */ | ||
802 | memset(&fake_ecryptfs_file, 0, sizeof(fake_ecryptfs_file)); | ||
803 | fake_ecryptfs_file.f_path.dentry = dentry; | ||
804 | /* Released at out_free: label */ | ||
805 | ecryptfs_set_file_private(&fake_ecryptfs_file, | ||
806 | kmem_cache_alloc(ecryptfs_file_info_cache, | ||
807 | GFP_KERNEL)); | ||
808 | if (unlikely(!ecryptfs_file_to_private(&fake_ecryptfs_file))) { | ||
809 | rc = -ENOMEM; | ||
810 | goto out; | ||
811 | } | ||
812 | lower_dentry = ecryptfs_dentry_to_lower(dentry); | ||
813 | ecryptfs_set_file_lower( | ||
814 | &fake_ecryptfs_file, | ||
815 | ecryptfs_inode_to_private(dentry->d_inode)->lower_file); | ||
816 | /* Switch on growing or shrinking file */ | 854 | /* Switch on growing or shrinking file */ |
817 | if (ia->ia_size > i_size) { | 855 | if (ia->ia_size > i_size) { |
818 | char zero[] = { 0x00 }; | 856 | char zero[] = { 0x00 }; |
@@ -822,7 +860,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia, | |||
822 | * this triggers code that will fill in 0's throughout | 860 | * this triggers code that will fill in 0's throughout |
823 | * the intermediate portion of the previous end of the | 861 | * the intermediate portion of the previous end of the |
824 | * file and the new and of the file */ | 862 | * file and the new and of the file */ |
825 | rc = ecryptfs_write(&fake_ecryptfs_file, zero, | 863 | rc = ecryptfs_write(inode, zero, |
826 | (ia->ia_size - 1), 1); | 864 | (ia->ia_size - 1), 1); |
827 | } else { /* ia->ia_size < i_size_read(inode) */ | 865 | } else { /* ia->ia_size < i_size_read(inode) */ |
828 | /* We're chopping off all the pages down to the page | 866 | /* We're chopping off all the pages down to the page |
@@ -832,13 +870,23 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia, | |||
832 | size_t num_zeros = (PAGE_CACHE_SIZE | 870 | size_t num_zeros = (PAGE_CACHE_SIZE |
833 | - (ia->ia_size & ~PAGE_CACHE_MASK)); | 871 | - (ia->ia_size & ~PAGE_CACHE_MASK)); |
834 | 872 | ||
873 | |||
874 | /* | ||
875 | * XXX(truncate) this should really happen at the begginning | ||
876 | * of ->setattr. But the code is too messy to that as part | ||
877 | * of a larger patch. ecryptfs is also totally missing out | ||
878 | * on the inode_change_ok check at the beginning of | ||
879 | * ->setattr while would include this. | ||
880 | */ | ||
881 | rc = inode_newsize_ok(inode, ia->ia_size); | ||
882 | if (rc) | ||
883 | goto out; | ||
884 | |||
835 | if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { | 885 | if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { |
836 | rc = vmtruncate(inode, ia->ia_size); | 886 | truncate_setsize(inode, ia->ia_size); |
837 | if (rc) | ||
838 | goto out_free; | ||
839 | lower_ia->ia_size = ia->ia_size; | 887 | lower_ia->ia_size = ia->ia_size; |
840 | lower_ia->ia_valid |= ATTR_SIZE; | 888 | lower_ia->ia_valid |= ATTR_SIZE; |
841 | goto out_free; | 889 | goto out; |
842 | } | 890 | } |
843 | if (num_zeros) { | 891 | if (num_zeros) { |
844 | char *zeros_virt; | 892 | char *zeros_virt; |
@@ -846,25 +894,25 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia, | |||
846 | zeros_virt = kzalloc(num_zeros, GFP_KERNEL); | 894 | zeros_virt = kzalloc(num_zeros, GFP_KERNEL); |
847 | if (!zeros_virt) { | 895 | if (!zeros_virt) { |
848 | rc = -ENOMEM; | 896 | rc = -ENOMEM; |
849 | goto out_free; | 897 | goto out; |
850 | } | 898 | } |
851 | rc = ecryptfs_write(&fake_ecryptfs_file, zeros_virt, | 899 | rc = ecryptfs_write(inode, zeros_virt, |
852 | ia->ia_size, num_zeros); | 900 | ia->ia_size, num_zeros); |
853 | kfree(zeros_virt); | 901 | kfree(zeros_virt); |
854 | if (rc) { | 902 | if (rc) { |
855 | printk(KERN_ERR "Error attempting to zero out " | 903 | printk(KERN_ERR "Error attempting to zero out " |
856 | "the remainder of the end page on " | 904 | "the remainder of the end page on " |
857 | "reducing truncate; rc = [%d]\n", rc); | 905 | "reducing truncate; rc = [%d]\n", rc); |
858 | goto out_free; | 906 | goto out; |
859 | } | 907 | } |
860 | } | 908 | } |
861 | vmtruncate(inode, ia->ia_size); | 909 | truncate_setsize(inode, ia->ia_size); |
862 | rc = ecryptfs_write_inode_size_to_metadata(inode); | 910 | rc = ecryptfs_write_inode_size_to_metadata(inode); |
863 | if (rc) { | 911 | if (rc) { |
864 | printk(KERN_ERR "Problem with " | 912 | printk(KERN_ERR "Problem with " |
865 | "ecryptfs_write_inode_size_to_metadata; " | 913 | "ecryptfs_write_inode_size_to_metadata; " |
866 | "rc = [%d]\n", rc); | 914 | "rc = [%d]\n", rc); |
867 | goto out_free; | 915 | goto out; |
868 | } | 916 | } |
869 | /* We are reducing the size of the ecryptfs file, and need to | 917 | /* We are reducing the size of the ecryptfs file, and need to |
870 | * know if we need to reduce the size of the lower file. */ | 918 | * know if we need to reduce the size of the lower file. */ |
@@ -878,10 +926,6 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia, | |||
878 | } else | 926 | } else |
879 | lower_ia->ia_valid &= ~ATTR_SIZE; | 927 | lower_ia->ia_valid &= ~ATTR_SIZE; |
880 | } | 928 | } |
881 | out_free: | ||
882 | if (ecryptfs_file_to_private(&fake_ecryptfs_file)) | ||
883 | kmem_cache_free(ecryptfs_file_info_cache, | ||
884 | ecryptfs_file_to_private(&fake_ecryptfs_file)); | ||
885 | out: | 929 | out: |
886 | return rc; | 930 | return rc; |
887 | } | 931 | } |