diff options
Diffstat (limited to 'fs/ecryptfs/inode.c')
-rw-r--r-- | fs/ecryptfs/inode.c | 90 |
1 files changed, 54 insertions, 36 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index d4f02f3e18d7..9fa7e0b27a96 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 1997-2004 Erez Zadok | 4 | * Copyright (C) 1997-2004 Erez Zadok |
5 | * Copyright (C) 2001-2004 Stony Brook University | 5 | * Copyright (C) 2001-2004 Stony Brook University |
6 | * Copyright (C) 2004-2006 International Business Machines Corp. | 6 | * Copyright (C) 2004-2007 International Business Machines Corp. |
7 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> | 7 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> |
8 | * Michael C. Thompsion <mcthomps@us.ibm.com> | 8 | * Michael C. Thompsion <mcthomps@us.ibm.com> |
9 | * | 9 | * |
@@ -161,17 +161,17 @@ static int grow_file(struct dentry *ecryptfs_dentry, struct file *lower_file, | |||
161 | ecryptfs_set_file_lower(&fake_file, lower_file); | 161 | ecryptfs_set_file_lower(&fake_file, lower_file); |
162 | rc = ecryptfs_fill_zeros(&fake_file, 1); | 162 | rc = ecryptfs_fill_zeros(&fake_file, 1); |
163 | if (rc) { | 163 | if (rc) { |
164 | ECRYPTFS_SET_FLAG( | 164 | ecryptfs_inode_to_private(inode)->crypt_stat.flags |= |
165 | ecryptfs_inode_to_private(inode)->crypt_stat.flags, | 165 | ECRYPTFS_SECURITY_WARNING; |
166 | ECRYPTFS_SECURITY_WARNING); | ||
167 | ecryptfs_printk(KERN_WARNING, "Error attempting to fill zeros " | 166 | ecryptfs_printk(KERN_WARNING, "Error attempting to fill zeros " |
168 | "in file; rc = [%d]\n", rc); | 167 | "in file; rc = [%d]\n", rc); |
169 | goto out; | 168 | goto out; |
170 | } | 169 | } |
171 | i_size_write(inode, 0); | 170 | i_size_write(inode, 0); |
172 | ecryptfs_write_inode_size_to_header(lower_file, lower_inode, inode); | 171 | ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode, inode, |
173 | ECRYPTFS_SET_FLAG(ecryptfs_inode_to_private(inode)->crypt_stat.flags, | 172 | ecryptfs_dentry, |
174 | ECRYPTFS_NEW_FILE); | 173 | ECRYPTFS_LOWER_I_MUTEX_NOT_HELD); |
174 | ecryptfs_inode_to_private(inode)->crypt_stat.flags |= ECRYPTFS_NEW_FILE; | ||
175 | out: | 175 | out: |
176 | return rc; | 176 | return rc; |
177 | } | 177 | } |
@@ -199,7 +199,7 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) | |||
199 | lower_dentry->d_name.name); | 199 | lower_dentry->d_name.name); |
200 | inode = ecryptfs_dentry->d_inode; | 200 | inode = ecryptfs_dentry->d_inode; |
201 | crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; | 201 | crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; |
202 | lower_flags = ((O_CREAT | O_WRONLY | O_TRUNC) & O_ACCMODE) | O_RDWR; | 202 | lower_flags = ((O_CREAT | O_TRUNC) & O_ACCMODE) | O_RDWR; |
203 | #if BITS_PER_LONG != 32 | 203 | #if BITS_PER_LONG != 32 |
204 | lower_flags |= O_LARGEFILE; | 204 | lower_flags |= O_LARGEFILE; |
205 | #endif | 205 | #endif |
@@ -214,10 +214,10 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) | |||
214 | lower_inode = lower_dentry->d_inode; | 214 | lower_inode = lower_dentry->d_inode; |
215 | if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { | 215 | if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { |
216 | ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); | 216 | ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); |
217 | ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); | 217 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); |
218 | goto out_fput; | 218 | goto out_fput; |
219 | } | 219 | } |
220 | ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE); | 220 | crypt_stat->flags |= ECRYPTFS_NEW_FILE; |
221 | ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n"); | 221 | ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n"); |
222 | rc = ecryptfs_new_file_context(ecryptfs_dentry); | 222 | rc = ecryptfs_new_file_context(ecryptfs_dentry); |
223 | if (rc) { | 223 | if (rc) { |
@@ -225,7 +225,7 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) | |||
225 | "context\n"); | 225 | "context\n"); |
226 | goto out_fput; | 226 | goto out_fput; |
227 | } | 227 | } |
228 | rc = ecryptfs_write_headers(ecryptfs_dentry, lower_file); | 228 | rc = ecryptfs_write_metadata(ecryptfs_dentry, lower_file); |
229 | if (rc) { | 229 | if (rc) { |
230 | ecryptfs_printk(KERN_DEBUG, "Error writing headers\n"); | 230 | ecryptfs_printk(KERN_DEBUG, "Error writing headers\n"); |
231 | goto out_fput; | 231 | goto out_fput; |
@@ -287,6 +287,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, | |||
287 | char *encoded_name; | 287 | char *encoded_name; |
288 | unsigned int encoded_namelen; | 288 | unsigned int encoded_namelen; |
289 | struct ecryptfs_crypt_stat *crypt_stat = NULL; | 289 | struct ecryptfs_crypt_stat *crypt_stat = NULL; |
290 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; | ||
290 | char *page_virt = NULL; | 291 | char *page_virt = NULL; |
291 | struct inode *lower_inode; | 292 | struct inode *lower_inode; |
292 | u64 file_size; | 293 | u64 file_size; |
@@ -362,32 +363,43 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, | |||
362 | } | 363 | } |
363 | /* Released in this function */ | 364 | /* Released in this function */ |
364 | page_virt = kmem_cache_zalloc(ecryptfs_header_cache_2, | 365 | page_virt = kmem_cache_zalloc(ecryptfs_header_cache_2, |
365 | GFP_USER); | 366 | GFP_USER); |
366 | if (!page_virt) { | 367 | if (!page_virt) { |
367 | rc = -ENOMEM; | 368 | rc = -ENOMEM; |
368 | ecryptfs_printk(KERN_ERR, | 369 | ecryptfs_printk(KERN_ERR, |
369 | "Cannot ecryptfs_kmalloc a page\n"); | 370 | "Cannot ecryptfs_kmalloc a page\n"); |
370 | goto out_dput; | 371 | goto out_dput; |
371 | } | 372 | } |
372 | |||
373 | rc = ecryptfs_read_header_region(page_virt, lower_dentry, nd->mnt); | ||
374 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; | 373 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; |
375 | if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) | 374 | if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) |
376 | ecryptfs_set_default_sizes(crypt_stat); | 375 | ecryptfs_set_default_sizes(crypt_stat); |
376 | rc = ecryptfs_read_and_validate_header_region(page_virt, lower_dentry, | ||
377 | nd->mnt); | ||
377 | if (rc) { | 378 | if (rc) { |
378 | rc = 0; | 379 | rc = ecryptfs_read_and_validate_xattr_region(page_virt, dentry); |
379 | ecryptfs_printk(KERN_WARNING, "Error reading header region;" | 380 | if (rc) { |
380 | " assuming unencrypted\n"); | 381 | printk(KERN_DEBUG "Valid metadata not found in header " |
381 | } else { | 382 | "region or xattr region; treating file as " |
382 | if (!contains_ecryptfs_marker(page_virt | 383 | "unencrypted\n"); |
383 | + ECRYPTFS_FILE_SIZE_BYTES)) { | 384 | rc = 0; |
384 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); | 385 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); |
385 | goto out; | 386 | goto out; |
386 | } | 387 | } |
388 | crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; | ||
389 | } | ||
390 | mount_crypt_stat = &ecryptfs_superblock_to_private( | ||
391 | dentry->d_sb)->mount_crypt_stat; | ||
392 | if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { | ||
393 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) | ||
394 | file_size = (crypt_stat->header_extent_size | ||
395 | + i_size_read(lower_dentry->d_inode)); | ||
396 | else | ||
397 | file_size = i_size_read(lower_dentry->d_inode); | ||
398 | } else { | ||
387 | memcpy(&file_size, page_virt, sizeof(file_size)); | 399 | memcpy(&file_size, page_virt, sizeof(file_size)); |
388 | file_size = be64_to_cpu(file_size); | 400 | file_size = be64_to_cpu(file_size); |
389 | i_size_write(dentry->d_inode, (loff_t)file_size); | ||
390 | } | 401 | } |
402 | i_size_write(dentry->d_inode, (loff_t)file_size); | ||
391 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); | 403 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); |
392 | goto out; | 404 | goto out; |
393 | 405 | ||
@@ -781,20 +793,26 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) | |||
781 | goto out_fput; | 793 | goto out_fput; |
782 | } | 794 | } |
783 | i_size_write(inode, new_length); | 795 | i_size_write(inode, new_length); |
784 | rc = ecryptfs_write_inode_size_to_header(lower_file, | 796 | rc = ecryptfs_write_inode_size_to_metadata( |
785 | lower_dentry->d_inode, | 797 | lower_file, lower_dentry->d_inode, inode, dentry, |
786 | inode); | 798 | ECRYPTFS_LOWER_I_MUTEX_NOT_HELD); |
787 | if (rc) { | 799 | if (rc) { |
788 | ecryptfs_printk(KERN_ERR, | 800 | printk(KERN_ERR "Problem with " |
789 | "Problem with ecryptfs_write" | 801 | "ecryptfs_write_inode_size_to_metadata; " |
790 | "_inode_size\n"); | 802 | "rc = [%d]\n", rc); |
791 | goto out_fput; | 803 | goto out_fput; |
792 | } | 804 | } |
793 | } else { /* new_length < i_size_read(inode) */ | 805 | } else { /* new_length < i_size_read(inode) */ |
794 | vmtruncate(inode, new_length); | 806 | vmtruncate(inode, new_length); |
795 | ecryptfs_write_inode_size_to_header(lower_file, | 807 | rc = ecryptfs_write_inode_size_to_metadata( |
796 | lower_dentry->d_inode, | 808 | lower_file, lower_dentry->d_inode, inode, dentry, |
797 | inode); | 809 | ECRYPTFS_LOWER_I_MUTEX_NOT_HELD); |
810 | if (rc) { | ||
811 | printk(KERN_ERR "Problem with " | ||
812 | "ecryptfs_write_inode_size_to_metadata; " | ||
813 | "rc = [%d]\n", rc); | ||
814 | goto out_fput; | ||
815 | } | ||
798 | /* We are reducing the size of the ecryptfs file, and need to | 816 | /* We are reducing the size of the ecryptfs file, and need to |
799 | * know if we need to reduce the size of the lower file. */ | 817 | * know if we need to reduce the size of the lower file. */ |
800 | lower_size_before_truncate = | 818 | lower_size_before_truncate = |
@@ -881,7 +899,7 @@ out: | |||
881 | return rc; | 899 | return rc; |
882 | } | 900 | } |
883 | 901 | ||
884 | static int | 902 | int |
885 | ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, | 903 | ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, |
886 | size_t size, int flags) | 904 | size_t size, int flags) |
887 | { | 905 | { |
@@ -901,7 +919,7 @@ out: | |||
901 | return rc; | 919 | return rc; |
902 | } | 920 | } |
903 | 921 | ||
904 | static ssize_t | 922 | ssize_t |
905 | ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value, | 923 | ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value, |
906 | size_t size) | 924 | size_t size) |
907 | { | 925 | { |
@@ -971,7 +989,7 @@ int ecryptfs_inode_set(struct inode *inode, void *lower_inode) | |||
971 | return 0; | 989 | return 0; |
972 | } | 990 | } |
973 | 991 | ||
974 | struct inode_operations ecryptfs_symlink_iops = { | 992 | const struct inode_operations ecryptfs_symlink_iops = { |
975 | .readlink = ecryptfs_readlink, | 993 | .readlink = ecryptfs_readlink, |
976 | .follow_link = ecryptfs_follow_link, | 994 | .follow_link = ecryptfs_follow_link, |
977 | .put_link = ecryptfs_put_link, | 995 | .put_link = ecryptfs_put_link, |
@@ -983,7 +1001,7 @@ struct inode_operations ecryptfs_symlink_iops = { | |||
983 | .removexattr = ecryptfs_removexattr | 1001 | .removexattr = ecryptfs_removexattr |
984 | }; | 1002 | }; |
985 | 1003 | ||
986 | struct inode_operations ecryptfs_dir_iops = { | 1004 | const struct inode_operations ecryptfs_dir_iops = { |
987 | .create = ecryptfs_create, | 1005 | .create = ecryptfs_create, |
988 | .lookup = ecryptfs_lookup, | 1006 | .lookup = ecryptfs_lookup, |
989 | .link = ecryptfs_link, | 1007 | .link = ecryptfs_link, |
@@ -1001,7 +1019,7 @@ struct inode_operations ecryptfs_dir_iops = { | |||
1001 | .removexattr = ecryptfs_removexattr | 1019 | .removexattr = ecryptfs_removexattr |
1002 | }; | 1020 | }; |
1003 | 1021 | ||
1004 | struct inode_operations ecryptfs_main_iops = { | 1022 | const struct inode_operations ecryptfs_main_iops = { |
1005 | .permission = ecryptfs_permission, | 1023 | .permission = ecryptfs_permission, |
1006 | .setattr = ecryptfs_setattr, | 1024 | .setattr = ecryptfs_setattr, |
1007 | .setxattr = ecryptfs_setxattr, | 1025 | .setxattr = ecryptfs_setxattr, |