diff options
| -rw-r--r-- | fs/ecryptfs/crypto.c | 21 | ||||
| -rw-r--r-- | fs/ecryptfs/ecryptfs_kernel.h | 7 | ||||
| -rw-r--r-- | fs/ecryptfs/file.c | 25 | ||||
| -rw-r--r-- | fs/ecryptfs/inode.c | 60 | ||||
| -rw-r--r-- | fs/ecryptfs/kthread.c | 6 | ||||
| -rw-r--r-- | fs/ecryptfs/main.c | 72 | ||||
| -rw-r--r-- | fs/ecryptfs/super.c | 16 |
7 files changed, 128 insertions, 79 deletions
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index d2a70a4561f9..b8d5c8091024 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c | |||
| @@ -1452,6 +1452,25 @@ static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat) | |||
| 1452 | crypt_stat->metadata_size = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; | 1452 | crypt_stat->metadata_size = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; |
| 1453 | } | 1453 | } |
| 1454 | 1454 | ||
| 1455 | void ecryptfs_i_size_init(const char *page_virt, struct inode *inode) | ||
| 1456 | { | ||
| 1457 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; | ||
| 1458 | struct ecryptfs_crypt_stat *crypt_stat; | ||
| 1459 | u64 file_size; | ||
| 1460 | |||
| 1461 | crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; | ||
| 1462 | mount_crypt_stat = | ||
| 1463 | &ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat; | ||
| 1464 | if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { | ||
| 1465 | file_size = i_size_read(ecryptfs_inode_to_lower(inode)); | ||
| 1466 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) | ||
| 1467 | file_size += crypt_stat->metadata_size; | ||
| 1468 | } else | ||
| 1469 | file_size = get_unaligned_be64(page_virt); | ||
| 1470 | i_size_write(inode, (loff_t)file_size); | ||
| 1471 | crypt_stat->flags |= ECRYPTFS_I_SIZE_INITIALIZED; | ||
| 1472 | } | ||
| 1473 | |||
| 1455 | /** | 1474 | /** |
| 1456 | * ecryptfs_read_headers_virt | 1475 | * ecryptfs_read_headers_virt |
| 1457 | * @page_virt: The virtual address into which to read the headers | 1476 | * @page_virt: The virtual address into which to read the headers |
| @@ -1482,6 +1501,8 @@ static int ecryptfs_read_headers_virt(char *page_virt, | |||
| 1482 | rc = -EINVAL; | 1501 | rc = -EINVAL; |
| 1483 | goto out; | 1502 | goto out; |
| 1484 | } | 1503 | } |
| 1504 | if (!(crypt_stat->flags & ECRYPTFS_I_SIZE_INITIALIZED)) | ||
| 1505 | ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode); | ||
| 1485 | offset += MAGIC_ECRYPTFS_MARKER_SIZE_BYTES; | 1506 | offset += MAGIC_ECRYPTFS_MARKER_SIZE_BYTES; |
| 1486 | rc = ecryptfs_process_flags(crypt_stat, (page_virt + offset), | 1507 | rc = ecryptfs_process_flags(crypt_stat, (page_virt + offset), |
| 1487 | &bytes_read); | 1508 | &bytes_read); |
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index bd3cafd0949d..e70282775e2c 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
| @@ -269,6 +269,7 @@ struct ecryptfs_crypt_stat { | |||
| 269 | #define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00000800 | 269 | #define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00000800 |
| 270 | #define ECRYPTFS_ENCFN_USE_FEK 0x00001000 | 270 | #define ECRYPTFS_ENCFN_USE_FEK 0x00001000 |
| 271 | #define ECRYPTFS_UNLINK_SIGS 0x00002000 | 271 | #define ECRYPTFS_UNLINK_SIGS 0x00002000 |
| 272 | #define ECRYPTFS_I_SIZE_INITIALIZED 0x00004000 | ||
| 272 | u32 flags; | 273 | u32 flags; |
| 273 | unsigned int file_version; | 274 | unsigned int file_version; |
| 274 | size_t iv_bytes; | 275 | size_t iv_bytes; |
| @@ -295,6 +296,8 @@ struct ecryptfs_crypt_stat { | |||
| 295 | struct ecryptfs_inode_info { | 296 | struct ecryptfs_inode_info { |
| 296 | struct inode vfs_inode; | 297 | struct inode vfs_inode; |
| 297 | struct inode *wii_inode; | 298 | struct inode *wii_inode; |
| 299 | struct mutex lower_file_mutex; | ||
| 300 | atomic_t lower_file_count; | ||
| 298 | struct file *lower_file; | 301 | struct file *lower_file; |
| 299 | struct ecryptfs_crypt_stat crypt_stat; | 302 | struct ecryptfs_crypt_stat crypt_stat; |
| 300 | }; | 303 | }; |
| @@ -626,6 +629,7 @@ struct ecryptfs_open_req { | |||
| 626 | int ecryptfs_interpose(struct dentry *hidden_dentry, | 629 | int ecryptfs_interpose(struct dentry *hidden_dentry, |
| 627 | struct dentry *this_dentry, struct super_block *sb, | 630 | struct dentry *this_dentry, struct super_block *sb, |
| 628 | u32 flags); | 631 | u32 flags); |
| 632 | void ecryptfs_i_size_init(const char *page_virt, struct inode *inode); | ||
| 629 | int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | 633 | int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, |
| 630 | struct dentry *lower_dentry, | 634 | struct dentry *lower_dentry, |
| 631 | struct inode *ecryptfs_dir_inode); | 635 | struct inode *ecryptfs_dir_inode); |
| @@ -757,7 +761,8 @@ int ecryptfs_privileged_open(struct file **lower_file, | |||
| 757 | struct dentry *lower_dentry, | 761 | struct dentry *lower_dentry, |
| 758 | struct vfsmount *lower_mnt, | 762 | struct vfsmount *lower_mnt, |
| 759 | const struct cred *cred); | 763 | const struct cred *cred); |
| 760 | int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry); | 764 | int ecryptfs_get_lower_file(struct dentry *ecryptfs_dentry); |
| 765 | void ecryptfs_put_lower_file(struct inode *inode); | ||
| 761 | int | 766 | int |
| 762 | ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, | 767 | ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, |
| 763 | size_t *packet_size, | 768 | size_t *packet_size, |
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index cedc913d11ba..566e5472f78c 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c | |||
| @@ -191,10 +191,10 @@ static int ecryptfs_open(struct inode *inode, struct file *file) | |||
| 191 | | ECRYPTFS_ENCRYPTED); | 191 | | ECRYPTFS_ENCRYPTED); |
| 192 | } | 192 | } |
| 193 | mutex_unlock(&crypt_stat->cs_mutex); | 193 | mutex_unlock(&crypt_stat->cs_mutex); |
| 194 | rc = ecryptfs_init_persistent_file(ecryptfs_dentry); | 194 | rc = ecryptfs_get_lower_file(ecryptfs_dentry); |
| 195 | if (rc) { | 195 | if (rc) { |
| 196 | printk(KERN_ERR "%s: Error attempting to initialize " | 196 | printk(KERN_ERR "%s: Error attempting to initialize " |
| 197 | "the persistent file for the dentry with name " | 197 | "the lower file for the dentry with name " |
| 198 | "[%s]; rc = [%d]\n", __func__, | 198 | "[%s]; rc = [%d]\n", __func__, |
| 199 | ecryptfs_dentry->d_name.name, rc); | 199 | ecryptfs_dentry->d_name.name, rc); |
| 200 | goto out_free; | 200 | goto out_free; |
| @@ -202,9 +202,9 @@ static int ecryptfs_open(struct inode *inode, struct file *file) | |||
| 202 | if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_ACCMODE) | 202 | if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_ACCMODE) |
| 203 | == O_RDONLY && (file->f_flags & O_ACCMODE) != O_RDONLY) { | 203 | == O_RDONLY && (file->f_flags & O_ACCMODE) != O_RDONLY) { |
| 204 | rc = -EPERM; | 204 | rc = -EPERM; |
| 205 | printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs " | 205 | printk(KERN_WARNING "%s: Lower file is RO; eCryptfs " |
| 206 | "file must hence be opened RO\n", __func__); | 206 | "file must hence be opened RO\n", __func__); |
| 207 | goto out_free; | 207 | goto out_put; |
| 208 | } | 208 | } |
| 209 | ecryptfs_set_file_lower( | 209 | ecryptfs_set_file_lower( |
| 210 | file, ecryptfs_inode_to_private(inode)->lower_file); | 210 | file, ecryptfs_inode_to_private(inode)->lower_file); |
| @@ -232,10 +232,11 @@ static int ecryptfs_open(struct inode *inode, struct file *file) | |||
| 232 | "Plaintext passthrough mode is not " | 232 | "Plaintext passthrough mode is not " |
| 233 | "enabled; returning -EIO\n"); | 233 | "enabled; returning -EIO\n"); |
| 234 | mutex_unlock(&crypt_stat->cs_mutex); | 234 | mutex_unlock(&crypt_stat->cs_mutex); |
| 235 | goto out_free; | 235 | goto out_put; |
| 236 | } | 236 | } |
| 237 | rc = 0; | 237 | rc = 0; |
| 238 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); | 238 | crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED |
| 239 | | ECRYPTFS_ENCRYPTED); | ||
| 239 | mutex_unlock(&crypt_stat->cs_mutex); | 240 | mutex_unlock(&crypt_stat->cs_mutex); |
| 240 | goto out; | 241 | goto out; |
| 241 | } | 242 | } |
| @@ -245,6 +246,8 @@ static int ecryptfs_open(struct inode *inode, struct file *file) | |||
| 245 | "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino, | 246 | "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino, |
| 246 | (unsigned long long)i_size_read(inode)); | 247 | (unsigned long long)i_size_read(inode)); |
| 247 | goto out; | 248 | goto out; |
| 249 | out_put: | ||
| 250 | ecryptfs_put_lower_file(inode); | ||
| 248 | out_free: | 251 | out_free: |
| 249 | kmem_cache_free(ecryptfs_file_info_cache, | 252 | kmem_cache_free(ecryptfs_file_info_cache, |
| 250 | ecryptfs_file_to_private(file)); | 253 | ecryptfs_file_to_private(file)); |
| @@ -254,17 +257,13 @@ out: | |||
| 254 | 257 | ||
| 255 | static int ecryptfs_flush(struct file *file, fl_owner_t td) | 258 | static int ecryptfs_flush(struct file *file, fl_owner_t td) |
| 256 | { | 259 | { |
| 257 | int rc = 0; | 260 | return file->f_mode & FMODE_WRITE |
| 258 | struct file *lower_file = NULL; | 261 | ? filemap_write_and_wait(file->f_mapping) : 0; |
| 259 | |||
| 260 | lower_file = ecryptfs_file_to_lower(file); | ||
| 261 | if (lower_file->f_op && lower_file->f_op->flush) | ||
| 262 | rc = lower_file->f_op->flush(lower_file, td); | ||
| 263 | return rc; | ||
| 264 | } | 262 | } |
| 265 | 263 | ||
| 266 | static int ecryptfs_release(struct inode *inode, struct file *file) | 264 | static int ecryptfs_release(struct inode *inode, struct file *file) |
| 267 | { | 265 | { |
| 266 | ecryptfs_put_lower_file(inode); | ||
| 268 | kmem_cache_free(ecryptfs_file_info_cache, | 267 | kmem_cache_free(ecryptfs_file_info_cache, |
| 269 | ecryptfs_file_to_private(file)); | 268 | ecryptfs_file_to_private(file)); |
| 270 | return 0; | 269 | return 0; |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index f99051b7adab..4d4cc6a90cd5 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
| @@ -168,19 +168,18 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) | |||
| 168 | "context; rc = [%d]\n", rc); | 168 | "context; rc = [%d]\n", rc); |
| 169 | goto out; | 169 | goto out; |
| 170 | } | 170 | } |
| 171 | rc = ecryptfs_init_persistent_file(ecryptfs_dentry); | 171 | rc = ecryptfs_get_lower_file(ecryptfs_dentry); |
| 172 | if (rc) { | 172 | if (rc) { |
| 173 | printk(KERN_ERR "%s: Error attempting to initialize " | 173 | printk(KERN_ERR "%s: Error attempting to initialize " |
| 174 | "the persistent file for the dentry with name " | 174 | "the lower file for the dentry with name " |
| 175 | "[%s]; rc = [%d]\n", __func__, | 175 | "[%s]; rc = [%d]\n", __func__, |
| 176 | ecryptfs_dentry->d_name.name, rc); | 176 | ecryptfs_dentry->d_name.name, rc); |
| 177 | goto out; | 177 | goto out; |
| 178 | } | 178 | } |
| 179 | rc = ecryptfs_write_metadata(ecryptfs_dentry); | 179 | rc = ecryptfs_write_metadata(ecryptfs_dentry); |
| 180 | if (rc) { | 180 | if (rc) |
| 181 | printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc); | 181 | printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc); |
| 182 | goto out; | 182 | ecryptfs_put_lower_file(ecryptfs_dentry->d_inode); |
| 183 | } | ||
| 184 | out: | 183 | out: |
| 185 | return rc; | 184 | return rc; |
| 186 | } | 185 | } |
| @@ -226,11 +225,9 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | |||
| 226 | struct dentry *lower_dir_dentry; | 225 | struct dentry *lower_dir_dentry; |
| 227 | struct vfsmount *lower_mnt; | 226 | struct vfsmount *lower_mnt; |
| 228 | struct inode *lower_inode; | 227 | struct inode *lower_inode; |
| 229 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; | ||
| 230 | struct ecryptfs_crypt_stat *crypt_stat; | 228 | struct ecryptfs_crypt_stat *crypt_stat; |
| 231 | char *page_virt = NULL; | 229 | char *page_virt = NULL; |
| 232 | u64 file_size; | 230 | int put_lower = 0, rc = 0; |
| 233 | int rc = 0; | ||
| 234 | 231 | ||
| 235 | lower_dir_dentry = lower_dentry->d_parent; | 232 | lower_dir_dentry = lower_dentry->d_parent; |
| 236 | lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt( | 233 | lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt( |
| @@ -277,14 +274,15 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | |||
| 277 | rc = -ENOMEM; | 274 | rc = -ENOMEM; |
| 278 | goto out; | 275 | goto out; |
| 279 | } | 276 | } |
| 280 | rc = ecryptfs_init_persistent_file(ecryptfs_dentry); | 277 | rc = ecryptfs_get_lower_file(ecryptfs_dentry); |
| 281 | if (rc) { | 278 | if (rc) { |
| 282 | printk(KERN_ERR "%s: Error attempting to initialize " | 279 | printk(KERN_ERR "%s: Error attempting to initialize " |
| 283 | "the persistent file for the dentry with name " | 280 | "the lower file for the dentry with name " |
| 284 | "[%s]; rc = [%d]\n", __func__, | 281 | "[%s]; rc = [%d]\n", __func__, |
| 285 | ecryptfs_dentry->d_name.name, rc); | 282 | ecryptfs_dentry->d_name.name, rc); |
| 286 | goto out_free_kmem; | 283 | goto out_free_kmem; |
| 287 | } | 284 | } |
| 285 | put_lower = 1; | ||
| 288 | crypt_stat = &ecryptfs_inode_to_private( | 286 | crypt_stat = &ecryptfs_inode_to_private( |
| 289 | ecryptfs_dentry->d_inode)->crypt_stat; | 287 | ecryptfs_dentry->d_inode)->crypt_stat; |
| 290 | /* TODO: lock for crypt_stat comparison */ | 288 | /* TODO: lock for crypt_stat comparison */ |
| @@ -302,18 +300,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | |||
| 302 | } | 300 | } |
| 303 | crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; | 301 | crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; |
| 304 | } | 302 | } |
| 305 | mount_crypt_stat = &ecryptfs_superblock_to_private( | 303 | ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode); |
| 306 | ecryptfs_dentry->d_sb)->mount_crypt_stat; | ||
| 307 | if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { | ||
| 308 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) | ||
| 309 | file_size = (crypt_stat->metadata_size | ||
| 310 | + i_size_read(lower_dentry->d_inode)); | ||
| 311 | else | ||
| 312 | file_size = i_size_read(lower_dentry->d_inode); | ||
| 313 | } else { | ||
| 314 | file_size = get_unaligned_be64(page_virt); | ||
| 315 | } | ||
| 316 | i_size_write(ecryptfs_dentry->d_inode, (loff_t)file_size); | ||
| 317 | out_free_kmem: | 304 | out_free_kmem: |
| 318 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); | 305 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); |
| 319 | goto out; | 306 | goto out; |
| @@ -322,6 +309,8 @@ out_put: | |||
| 322 | mntput(lower_mnt); | 309 | mntput(lower_mnt); |
| 323 | d_drop(ecryptfs_dentry); | 310 | d_drop(ecryptfs_dentry); |
| 324 | out: | 311 | out: |
| 312 | if (put_lower) | ||
| 313 | ecryptfs_put_lower_file(ecryptfs_dentry->d_inode); | ||
| 325 | return rc; | 314 | return rc; |
| 326 | } | 315 | } |
| 327 | 316 | ||
| @@ -538,8 +527,6 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 538 | dget(lower_dentry); | 527 | dget(lower_dentry); |
| 539 | rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); | 528 | rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); |
| 540 | dput(lower_dentry); | 529 | dput(lower_dentry); |
| 541 | if (!rc) | ||
| 542 | d_delete(lower_dentry); | ||
| 543 | fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); | 530 | fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); |
| 544 | dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; | 531 | dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; |
| 545 | unlock_dir(lower_dir_dentry); | 532 | unlock_dir(lower_dir_dentry); |
| @@ -610,8 +597,8 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 610 | fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode); | 597 | fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode); |
| 611 | out_lock: | 598 | out_lock: |
| 612 | unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); | 599 | unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); |
| 613 | dput(lower_new_dentry->d_parent); | 600 | dput(lower_new_dir_dentry); |
| 614 | dput(lower_old_dentry->d_parent); | 601 | dput(lower_old_dir_dentry); |
| 615 | dput(lower_new_dentry); | 602 | dput(lower_new_dentry); |
| 616 | dput(lower_old_dentry); | 603 | dput(lower_old_dentry); |
| 617 | return rc; | 604 | return rc; |
| @@ -759,8 +746,11 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia, | |||
| 759 | 746 | ||
| 760 | if (unlikely((ia->ia_size == i_size))) { | 747 | if (unlikely((ia->ia_size == i_size))) { |
| 761 | lower_ia->ia_valid &= ~ATTR_SIZE; | 748 | lower_ia->ia_valid &= ~ATTR_SIZE; |
| 762 | goto out; | 749 | return 0; |
| 763 | } | 750 | } |
| 751 | rc = ecryptfs_get_lower_file(dentry); | ||
| 752 | if (rc) | ||
| 753 | return rc; | ||
| 764 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; | 754 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; |
| 765 | /* Switch on growing or shrinking file */ | 755 | /* Switch on growing or shrinking file */ |
| 766 | if (ia->ia_size > i_size) { | 756 | if (ia->ia_size > i_size) { |
| @@ -838,6 +828,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia, | |||
| 838 | lower_ia->ia_valid &= ~ATTR_SIZE; | 828 | lower_ia->ia_valid &= ~ATTR_SIZE; |
| 839 | } | 829 | } |
| 840 | out: | 830 | out: |
| 831 | ecryptfs_put_lower_file(inode); | ||
| 841 | return rc; | 832 | return rc; |
| 842 | } | 833 | } |
| 843 | 834 | ||
| @@ -913,7 +904,13 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) | |||
| 913 | 904 | ||
| 914 | mount_crypt_stat = &ecryptfs_superblock_to_private( | 905 | mount_crypt_stat = &ecryptfs_superblock_to_private( |
| 915 | dentry->d_sb)->mount_crypt_stat; | 906 | dentry->d_sb)->mount_crypt_stat; |
| 907 | rc = ecryptfs_get_lower_file(dentry); | ||
| 908 | if (rc) { | ||
| 909 | mutex_unlock(&crypt_stat->cs_mutex); | ||
| 910 | goto out; | ||
| 911 | } | ||
| 916 | rc = ecryptfs_read_metadata(dentry); | 912 | rc = ecryptfs_read_metadata(dentry); |
| 913 | ecryptfs_put_lower_file(inode); | ||
| 917 | if (rc) { | 914 | if (rc) { |
| 918 | if (!(mount_crypt_stat->flags | 915 | if (!(mount_crypt_stat->flags |
| 919 | & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { | 916 | & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { |
| @@ -927,10 +924,17 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) | |||
| 927 | goto out; | 924 | goto out; |
| 928 | } | 925 | } |
| 929 | rc = 0; | 926 | rc = 0; |
| 930 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); | 927 | crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED |
| 928 | | ECRYPTFS_ENCRYPTED); | ||
| 931 | } | 929 | } |
| 932 | } | 930 | } |
| 933 | mutex_unlock(&crypt_stat->cs_mutex); | 931 | mutex_unlock(&crypt_stat->cs_mutex); |
| 932 | if (S_ISREG(inode->i_mode)) { | ||
| 933 | rc = filemap_write_and_wait(inode->i_mapping); | ||
| 934 | if (rc) | ||
| 935 | goto out; | ||
| 936 | fsstack_copy_attr_all(inode, lower_inode); | ||
| 937 | } | ||
| 934 | memcpy(&lower_ia, ia, sizeof(lower_ia)); | 938 | memcpy(&lower_ia, ia, sizeof(lower_ia)); |
| 935 | if (ia->ia_valid & ATTR_FILE) | 939 | if (ia->ia_valid & ATTR_FILE) |
| 936 | lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file); | 940 | lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file); |
diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c index 0851ab6980f5..69f994a7d524 100644 --- a/fs/ecryptfs/kthread.c +++ b/fs/ecryptfs/kthread.c | |||
| @@ -44,7 +44,7 @@ static struct task_struct *ecryptfs_kthread; | |||
| 44 | * @ignored: ignored | 44 | * @ignored: ignored |
| 45 | * | 45 | * |
| 46 | * The eCryptfs kernel thread that has the responsibility of getting | 46 | * The eCryptfs kernel thread that has the responsibility of getting |
| 47 | * the lower persistent file with RW permissions. | 47 | * the lower file with RW permissions. |
| 48 | * | 48 | * |
| 49 | * Returns zero on success; non-zero otherwise | 49 | * Returns zero on success; non-zero otherwise |
| 50 | */ | 50 | */ |
| @@ -141,8 +141,8 @@ int ecryptfs_privileged_open(struct file **lower_file, | |||
| 141 | int rc = 0; | 141 | int rc = 0; |
| 142 | 142 | ||
| 143 | /* Corresponding dput() and mntput() are done when the | 143 | /* Corresponding dput() and mntput() are done when the |
| 144 | * persistent file is fput() when the eCryptfs inode is | 144 | * lower file is fput() when all eCryptfs files for the inode are |
| 145 | * destroyed. */ | 145 | * released. */ |
| 146 | dget(lower_dentry); | 146 | dget(lower_dentry); |
| 147 | mntget(lower_mnt); | 147 | mntget(lower_mnt); |
| 148 | flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; | 148 | flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; |
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index fdb2eb0ad09e..89b93389af8e 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c | |||
| @@ -96,7 +96,7 @@ void __ecryptfs_printk(const char *fmt, ...) | |||
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | /** | 98 | /** |
| 99 | * ecryptfs_init_persistent_file | 99 | * ecryptfs_init_lower_file |
| 100 | * @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with | 100 | * @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with |
| 101 | * the lower dentry and the lower mount set | 101 | * the lower dentry and the lower mount set |
| 102 | * | 102 | * |
| @@ -104,42 +104,70 @@ void __ecryptfs_printk(const char *fmt, ...) | |||
| 104 | * inode. All I/O operations to the lower inode occur through that | 104 | * inode. All I/O operations to the lower inode occur through that |
| 105 | * file. When the first eCryptfs dentry that interposes with the first | 105 | * file. When the first eCryptfs dentry that interposes with the first |
| 106 | * lower dentry for that inode is created, this function creates the | 106 | * lower dentry for that inode is created, this function creates the |
| 107 | * persistent file struct and associates it with the eCryptfs | 107 | * lower file struct and associates it with the eCryptfs |
| 108 | * inode. When the eCryptfs inode is destroyed, the file is closed. | 108 | * inode. When all eCryptfs files associated with the inode are released, the |
| 109 | * file is closed. | ||
| 109 | * | 110 | * |
| 110 | * The persistent file will be opened with read/write permissions, if | 111 | * The lower file will be opened with read/write permissions, if |
| 111 | * possible. Otherwise, it is opened read-only. | 112 | * possible. Otherwise, it is opened read-only. |
| 112 | * | 113 | * |
| 113 | * This function does nothing if a lower persistent file is already | 114 | * This function does nothing if a lower file is already |
| 114 | * associated with the eCryptfs inode. | 115 | * associated with the eCryptfs inode. |
| 115 | * | 116 | * |
| 116 | * Returns zero on success; non-zero otherwise | 117 | * Returns zero on success; non-zero otherwise |
| 117 | */ | 118 | */ |
| 118 | int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry) | 119 | static int ecryptfs_init_lower_file(struct dentry *dentry, |
| 120 | struct file **lower_file) | ||
| 119 | { | 121 | { |
| 120 | const struct cred *cred = current_cred(); | 122 | const struct cred *cred = current_cred(); |
| 121 | struct ecryptfs_inode_info *inode_info = | 123 | struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); |
| 122 | ecryptfs_inode_to_private(ecryptfs_dentry->d_inode); | 124 | struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); |
| 123 | int rc = 0; | 125 | int rc; |
| 124 | 126 | ||
| 125 | if (!inode_info->lower_file) { | 127 | rc = ecryptfs_privileged_open(lower_file, lower_dentry, lower_mnt, |
| 126 | struct dentry *lower_dentry; | 128 | cred); |
| 127 | struct vfsmount *lower_mnt = | 129 | if (rc) { |
| 128 | ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); | 130 | printk(KERN_ERR "Error opening lower file " |
| 131 | "for lower_dentry [0x%p] and lower_mnt [0x%p]; " | ||
| 132 | "rc = [%d]\n", lower_dentry, lower_mnt, rc); | ||
| 133 | (*lower_file) = NULL; | ||
| 134 | } | ||
| 135 | return rc; | ||
| 136 | } | ||
| 129 | 137 | ||
| 130 | lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); | 138 | int ecryptfs_get_lower_file(struct dentry *dentry) |
| 131 | rc = ecryptfs_privileged_open(&inode_info->lower_file, | 139 | { |
| 132 | lower_dentry, lower_mnt, cred); | 140 | struct ecryptfs_inode_info *inode_info = |
| 133 | if (rc) { | 141 | ecryptfs_inode_to_private(dentry->d_inode); |
| 134 | printk(KERN_ERR "Error opening lower persistent file " | 142 | int count, rc = 0; |
| 135 | "for lower_dentry [0x%p] and lower_mnt [0x%p]; " | 143 | |
| 136 | "rc = [%d]\n", lower_dentry, lower_mnt, rc); | 144 | mutex_lock(&inode_info->lower_file_mutex); |
| 137 | inode_info->lower_file = NULL; | 145 | count = atomic_inc_return(&inode_info->lower_file_count); |
| 138 | } | 146 | if (WARN_ON_ONCE(count < 1)) |
| 147 | rc = -EINVAL; | ||
| 148 | else if (count == 1) { | ||
| 149 | rc = ecryptfs_init_lower_file(dentry, | ||
| 150 | &inode_info->lower_file); | ||
| 151 | if (rc) | ||
| 152 | atomic_set(&inode_info->lower_file_count, 0); | ||
| 139 | } | 153 | } |
| 154 | mutex_unlock(&inode_info->lower_file_mutex); | ||
| 140 | return rc; | 155 | return rc; |
| 141 | } | 156 | } |
| 142 | 157 | ||
| 158 | void ecryptfs_put_lower_file(struct inode *inode) | ||
| 159 | { | ||
| 160 | struct ecryptfs_inode_info *inode_info; | ||
| 161 | |||
| 162 | inode_info = ecryptfs_inode_to_private(inode); | ||
| 163 | if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count, | ||
| 164 | &inode_info->lower_file_mutex)) { | ||
| 165 | fput(inode_info->lower_file); | ||
| 166 | inode_info->lower_file = NULL; | ||
| 167 | mutex_unlock(&inode_info->lower_file_mutex); | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 143 | static struct inode *ecryptfs_get_inode(struct inode *lower_inode, | 171 | static struct inode *ecryptfs_get_inode(struct inode *lower_inode, |
| 144 | struct super_block *sb) | 172 | struct super_block *sb) |
| 145 | { | 173 | { |
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index bacc882e1ae4..245b517bf1b6 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c | |||
| @@ -55,6 +55,8 @@ static struct inode *ecryptfs_alloc_inode(struct super_block *sb) | |||
| 55 | if (unlikely(!inode_info)) | 55 | if (unlikely(!inode_info)) |
| 56 | goto out; | 56 | goto out; |
| 57 | ecryptfs_init_crypt_stat(&inode_info->crypt_stat); | 57 | ecryptfs_init_crypt_stat(&inode_info->crypt_stat); |
| 58 | mutex_init(&inode_info->lower_file_mutex); | ||
| 59 | atomic_set(&inode_info->lower_file_count, 0); | ||
| 58 | inode_info->lower_file = NULL; | 60 | inode_info->lower_file = NULL; |
| 59 | inode = &inode_info->vfs_inode; | 61 | inode = &inode_info->vfs_inode; |
| 60 | out: | 62 | out: |
| @@ -77,8 +79,7 @@ static void ecryptfs_i_callback(struct rcu_head *head) | |||
| 77 | * | 79 | * |
| 78 | * This is used during the final destruction of the inode. All | 80 | * This is used during the final destruction of the inode. All |
| 79 | * allocation of memory related to the inode, including allocated | 81 | * allocation of memory related to the inode, including allocated |
| 80 | * memory in the crypt_stat struct, will be released here. This | 82 | * memory in the crypt_stat struct, will be released here. |
| 81 | * function also fput()'s the persistent file for the lower inode. | ||
| 82 | * There should be no chance that this deallocation will be missed. | 83 | * There should be no chance that this deallocation will be missed. |
| 83 | */ | 84 | */ |
| 84 | static void ecryptfs_destroy_inode(struct inode *inode) | 85 | static void ecryptfs_destroy_inode(struct inode *inode) |
| @@ -86,16 +87,7 @@ static void ecryptfs_destroy_inode(struct inode *inode) | |||
| 86 | struct ecryptfs_inode_info *inode_info; | 87 | struct ecryptfs_inode_info *inode_info; |
| 87 | 88 | ||
| 88 | inode_info = ecryptfs_inode_to_private(inode); | 89 | inode_info = ecryptfs_inode_to_private(inode); |
| 89 | if (inode_info->lower_file) { | 90 | BUG_ON(inode_info->lower_file); |
| 90 | struct dentry *lower_dentry = | ||
| 91 | inode_info->lower_file->f_dentry; | ||
| 92 | |||
| 93 | BUG_ON(!lower_dentry); | ||
| 94 | if (lower_dentry->d_inode) { | ||
| 95 | fput(inode_info->lower_file); | ||
| 96 | inode_info->lower_file = NULL; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat); | 91 | ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat); |
| 100 | call_rcu(&inode->i_rcu, ecryptfs_i_callback); | 92 | call_rcu(&inode->i_rcu, ecryptfs_i_callback); |
| 101 | } | 93 | } |
