diff options
Diffstat (limited to 'fs/ecryptfs/inode.c')
-rw-r--r-- | fs/ecryptfs/inode.c | 134 |
1 files changed, 69 insertions, 65 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 704a8c8fe19a..fc7d2b748503 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -58,85 +58,87 @@ static int ecryptfs_inode_test(struct inode *inode, void *lower_inode) | |||
58 | return 0; | 58 | return 0; |
59 | } | 59 | } |
60 | 60 | ||
61 | static int ecryptfs_inode_set(struct inode *inode, void *lower_inode) | 61 | static int ecryptfs_inode_set(struct inode *inode, void *opaque) |
62 | { | 62 | { |
63 | ecryptfs_set_inode_lower(inode, (struct inode *)lower_inode); | 63 | struct inode *lower_inode = opaque; |
64 | inode->i_ino = ((struct inode *)lower_inode)->i_ino; | 64 | |
65 | ecryptfs_set_inode_lower(inode, lower_inode); | ||
66 | fsstack_copy_attr_all(inode, lower_inode); | ||
67 | /* i_size will be overwritten for encrypted regular files */ | ||
68 | fsstack_copy_inode_size(inode, lower_inode); | ||
69 | inode->i_ino = lower_inode->i_ino; | ||
65 | inode->i_version++; | 70 | inode->i_version++; |
66 | inode->i_op = &ecryptfs_main_iops; | ||
67 | inode->i_fop = &ecryptfs_main_fops; | ||
68 | inode->i_mapping->a_ops = &ecryptfs_aops; | 71 | inode->i_mapping->a_ops = &ecryptfs_aops; |
72 | |||
73 | if (S_ISLNK(inode->i_mode)) | ||
74 | inode->i_op = &ecryptfs_symlink_iops; | ||
75 | else if (S_ISDIR(inode->i_mode)) | ||
76 | inode->i_op = &ecryptfs_dir_iops; | ||
77 | else | ||
78 | inode->i_op = &ecryptfs_main_iops; | ||
79 | |||
80 | if (S_ISDIR(inode->i_mode)) | ||
81 | inode->i_fop = &ecryptfs_dir_fops; | ||
82 | else if (special_file(inode->i_mode)) | ||
83 | init_special_inode(inode, inode->i_mode, inode->i_rdev); | ||
84 | else | ||
85 | inode->i_fop = &ecryptfs_main_fops; | ||
86 | |||
69 | return 0; | 87 | return 0; |
70 | } | 88 | } |
71 | 89 | ||
72 | struct inode *ecryptfs_get_inode(struct inode *lower_inode, | 90 | static struct inode *__ecryptfs_get_inode(struct inode *lower_inode, |
73 | struct super_block *sb) | 91 | struct super_block *sb) |
74 | { | 92 | { |
75 | struct inode *inode; | 93 | struct inode *inode; |
76 | int rc = 0; | ||
77 | 94 | ||
78 | if (lower_inode->i_sb != ecryptfs_superblock_to_lower(sb)) { | 95 | if (lower_inode->i_sb != ecryptfs_superblock_to_lower(sb)) |
79 | rc = -EXDEV; | 96 | return ERR_PTR(-EXDEV); |
80 | goto out; | 97 | if (!igrab(lower_inode)) |
81 | } | 98 | return ERR_PTR(-ESTALE); |
82 | if (!igrab(lower_inode)) { | ||
83 | rc = -ESTALE; | ||
84 | goto out; | ||
85 | } | ||
86 | inode = iget5_locked(sb, (unsigned long)lower_inode, | 99 | inode = iget5_locked(sb, (unsigned long)lower_inode, |
87 | ecryptfs_inode_test, ecryptfs_inode_set, | 100 | ecryptfs_inode_test, ecryptfs_inode_set, |
88 | lower_inode); | 101 | lower_inode); |
89 | if (!inode) { | 102 | if (!inode) { |
90 | rc = -EACCES; | ||
91 | iput(lower_inode); | 103 | iput(lower_inode); |
92 | goto out; | 104 | return ERR_PTR(-EACCES); |
93 | } | 105 | } |
94 | if (inode->i_state & I_NEW) | 106 | if (!(inode->i_state & I_NEW)) |
95 | unlock_new_inode(inode); | ||
96 | else | ||
97 | iput(lower_inode); | 107 | iput(lower_inode); |
98 | if (S_ISLNK(lower_inode->i_mode)) | 108 | |
99 | inode->i_op = &ecryptfs_symlink_iops; | 109 | return inode; |
100 | else if (S_ISDIR(lower_inode->i_mode)) | 110 | } |
101 | inode->i_op = &ecryptfs_dir_iops; | 111 | |
102 | if (S_ISDIR(lower_inode->i_mode)) | 112 | struct inode *ecryptfs_get_inode(struct inode *lower_inode, |
103 | inode->i_fop = &ecryptfs_dir_fops; | 113 | struct super_block *sb) |
104 | if (special_file(lower_inode->i_mode)) | 114 | { |
105 | init_special_inode(inode, lower_inode->i_mode, | 115 | struct inode *inode = __ecryptfs_get_inode(lower_inode, sb); |
106 | lower_inode->i_rdev); | 116 | |
107 | fsstack_copy_attr_all(inode, lower_inode); | 117 | if (!IS_ERR(inode) && (inode->i_state & I_NEW)) |
108 | /* This size will be overwritten for real files w/ headers and | 118 | unlock_new_inode(inode); |
109 | * other metadata */ | 119 | |
110 | fsstack_copy_inode_size(inode, lower_inode); | ||
111 | return inode; | 120 | return inode; |
112 | out: | ||
113 | return ERR_PTR(rc); | ||
114 | } | 121 | } |
115 | 122 | ||
116 | #define ECRYPTFS_INTERPOSE_FLAG_D_ADD 0x00000001 | ||
117 | /** | 123 | /** |
118 | * ecryptfs_interpose | 124 | * ecryptfs_interpose |
119 | * @lower_dentry: Existing dentry in the lower filesystem | 125 | * @lower_dentry: Existing dentry in the lower filesystem |
120 | * @dentry: ecryptfs' dentry | 126 | * @dentry: ecryptfs' dentry |
121 | * @sb: ecryptfs's super_block | 127 | * @sb: ecryptfs's super_block |
122 | * @flags: flags to govern behavior of interpose procedure | ||
123 | * | 128 | * |
124 | * Interposes upper and lower dentries. | 129 | * Interposes upper and lower dentries. |
125 | * | 130 | * |
126 | * Returns zero on success; non-zero otherwise | 131 | * Returns zero on success; non-zero otherwise |
127 | */ | 132 | */ |
128 | static int ecryptfs_interpose(struct dentry *lower_dentry, | 133 | static int ecryptfs_interpose(struct dentry *lower_dentry, |
129 | struct dentry *dentry, struct super_block *sb, | 134 | struct dentry *dentry, struct super_block *sb) |
130 | u32 flags) | ||
131 | { | 135 | { |
132 | struct inode *lower_inode = lower_dentry->d_inode; | 136 | struct inode *inode = ecryptfs_get_inode(lower_dentry->d_inode, sb); |
133 | struct inode *inode = ecryptfs_get_inode(lower_inode, sb); | 137 | |
134 | if (IS_ERR(inode)) | 138 | if (IS_ERR(inode)) |
135 | return PTR_ERR(inode); | 139 | return PTR_ERR(inode); |
136 | if (flags & ECRYPTFS_INTERPOSE_FLAG_D_ADD) | 140 | d_instantiate(dentry, inode); |
137 | d_add(dentry, inode); | 141 | |
138 | else | ||
139 | d_instantiate(dentry, inode); | ||
140 | return 0; | 142 | return 0; |
141 | } | 143 | } |
142 | 144 | ||
@@ -218,7 +220,7 @@ ecryptfs_do_create(struct inode *directory_inode, | |||
218 | goto out_lock; | 220 | goto out_lock; |
219 | } | 221 | } |
220 | rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry, | 222 | rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry, |
221 | directory_inode->i_sb, 0); | 223 | directory_inode->i_sb); |
222 | if (rc) { | 224 | if (rc) { |
223 | ecryptfs_printk(KERN_ERR, "Failure in ecryptfs_interpose\n"); | 225 | ecryptfs_printk(KERN_ERR, "Failure in ecryptfs_interpose\n"); |
224 | goto out_lock; | 226 | goto out_lock; |
@@ -305,15 +307,15 @@ out: | |||
305 | } | 307 | } |
306 | 308 | ||
307 | /** | 309 | /** |
308 | * ecryptfs_lookup_and_interpose_lower - Perform a lookup | 310 | * ecryptfs_lookup_interpose - Dentry interposition for a lookup |
309 | */ | 311 | */ |
310 | int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | 312 | static int ecryptfs_lookup_interpose(struct dentry *ecryptfs_dentry, |
311 | struct dentry *lower_dentry, | 313 | struct dentry *lower_dentry, |
312 | struct inode *ecryptfs_dir_inode) | 314 | struct inode *ecryptfs_dir_inode) |
313 | { | 315 | { |
314 | struct dentry *lower_dir_dentry; | 316 | struct dentry *lower_dir_dentry; |
315 | struct vfsmount *lower_mnt; | 317 | struct vfsmount *lower_mnt; |
316 | struct inode *lower_inode; | 318 | struct inode *inode, *lower_inode; |
317 | struct ecryptfs_crypt_stat *crypt_stat; | 319 | struct ecryptfs_crypt_stat *crypt_stat; |
318 | char *page_virt = NULL; | 320 | char *page_virt = NULL; |
319 | int put_lower = 0, rc = 0; | 321 | int put_lower = 0, rc = 0; |
@@ -341,14 +343,16 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | |||
341 | d_add(ecryptfs_dentry, NULL); | 343 | d_add(ecryptfs_dentry, NULL); |
342 | goto out; | 344 | goto out; |
343 | } | 345 | } |
344 | rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry, | 346 | inode = __ecryptfs_get_inode(lower_inode, ecryptfs_dir_inode->i_sb); |
345 | ecryptfs_dir_inode->i_sb, | 347 | if (IS_ERR(inode)) { |
346 | ECRYPTFS_INTERPOSE_FLAG_D_ADD); | 348 | rc = PTR_ERR(inode); |
347 | if (rc) { | ||
348 | printk(KERN_ERR "%s: Error interposing; rc = [%d]\n", | 349 | printk(KERN_ERR "%s: Error interposing; rc = [%d]\n", |
349 | __func__, rc); | 350 | __func__, rc); |
350 | goto out; | 351 | goto out; |
351 | } | 352 | } |
353 | if (inode->i_state & I_NEW) | ||
354 | unlock_new_inode(inode); | ||
355 | d_add(ecryptfs_dentry, inode); | ||
352 | if (S_ISDIR(lower_inode->i_mode)) | 356 | if (S_ISDIR(lower_inode->i_mode)) |
353 | goto out; | 357 | goto out; |
354 | if (S_ISLNK(lower_inode->i_mode)) | 358 | if (S_ISLNK(lower_inode->i_mode)) |
@@ -442,12 +446,12 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
442 | goto out_d_drop; | 446 | goto out_d_drop; |
443 | } | 447 | } |
444 | if (lower_dentry->d_inode) | 448 | if (lower_dentry->d_inode) |
445 | goto lookup_and_interpose; | 449 | goto interpose; |
446 | mount_crypt_stat = &ecryptfs_superblock_to_private( | 450 | mount_crypt_stat = &ecryptfs_superblock_to_private( |
447 | ecryptfs_dentry->d_sb)->mount_crypt_stat; | 451 | ecryptfs_dentry->d_sb)->mount_crypt_stat; |
448 | if (!(mount_crypt_stat | 452 | if (!(mount_crypt_stat |
449 | && (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES))) | 453 | && (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES))) |
450 | goto lookup_and_interpose; | 454 | goto interpose; |
451 | dput(lower_dentry); | 455 | dput(lower_dentry); |
452 | rc = ecryptfs_encrypt_and_encode_filename( | 456 | rc = ecryptfs_encrypt_and_encode_filename( |
453 | &encrypted_and_encoded_name, &encrypted_and_encoded_name_size, | 457 | &encrypted_and_encoded_name, &encrypted_and_encoded_name_size, |
@@ -470,9 +474,9 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
470 | encrypted_and_encoded_name); | 474 | encrypted_and_encoded_name); |
471 | goto out_d_drop; | 475 | goto out_d_drop; |
472 | } | 476 | } |
473 | lookup_and_interpose: | 477 | interpose: |
474 | rc = ecryptfs_lookup_and_interpose_lower(ecryptfs_dentry, lower_dentry, | 478 | rc = ecryptfs_lookup_interpose(ecryptfs_dentry, lower_dentry, |
475 | ecryptfs_dir_inode); | 479 | ecryptfs_dir_inode); |
476 | goto out; | 480 | goto out; |
477 | out_d_drop: | 481 | out_d_drop: |
478 | d_drop(ecryptfs_dentry); | 482 | d_drop(ecryptfs_dentry); |
@@ -500,7 +504,7 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir, | |||
500 | lower_new_dentry); | 504 | lower_new_dentry); |
501 | if (rc || !lower_new_dentry->d_inode) | 505 | if (rc || !lower_new_dentry->d_inode) |
502 | goto out_lock; | 506 | goto out_lock; |
503 | rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0); | 507 | rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb); |
504 | if (rc) | 508 | if (rc) |
505 | goto out_lock; | 509 | goto out_lock; |
506 | fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); | 510 | fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); |
@@ -567,7 +571,7 @@ static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry, | |||
567 | kfree(encoded_symname); | 571 | kfree(encoded_symname); |
568 | if (rc || !lower_dentry->d_inode) | 572 | if (rc || !lower_dentry->d_inode) |
569 | goto out_lock; | 573 | goto out_lock; |
570 | rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0); | 574 | rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb); |
571 | if (rc) | 575 | if (rc) |
572 | goto out_lock; | 576 | goto out_lock; |
573 | fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); | 577 | fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); |
@@ -591,7 +595,7 @@ static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
591 | rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, mode); | 595 | rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, mode); |
592 | if (rc || !lower_dentry->d_inode) | 596 | if (rc || !lower_dentry->d_inode) |
593 | goto out; | 597 | goto out; |
594 | rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0); | 598 | rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb); |
595 | if (rc) | 599 | if (rc) |
596 | goto out; | 600 | goto out; |
597 | fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); | 601 | fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); |
@@ -639,7 +643,7 @@ ecryptfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) | |||
639 | rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, mode, dev); | 643 | rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, mode, dev); |
640 | if (rc || !lower_dentry->d_inode) | 644 | if (rc || !lower_dentry->d_inode) |
641 | goto out; | 645 | goto out; |
642 | rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0); | 646 | rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb); |
643 | if (rc) | 647 | if (rc) |
644 | goto out; | 648 | goto out; |
645 | fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); | 649 | fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); |