aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h6
-rw-r--r--fs/ecryptfs/file.c14
-rw-r--r--fs/ecryptfs/inode.c6
-rw-r--r--fs/ecryptfs/main.c29
4 files changed, 42 insertions, 13 deletions
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index b4a0cccfdd7c..b0727f91454e 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -235,6 +235,7 @@ struct ecryptfs_crypt_stat {
235#define ECRYPTFS_METADATA_IN_XATTR 0x00000100 235#define ECRYPTFS_METADATA_IN_XATTR 0x00000100
236#define ECRYPTFS_VIEW_AS_ENCRYPTED 0x00000200 236#define ECRYPTFS_VIEW_AS_ENCRYPTED 0x00000200
237#define ECRYPTFS_KEY_SET 0x00000400 237#define ECRYPTFS_KEY_SET 0x00000400
238#define ECRYPTFS_DELAY_PERSISTENT 0x00000800
238 u32 flags; 239 u32 flags;
239 unsigned int file_version; 240 unsigned int file_version;
240 size_t iv_bytes; 241 size_t iv_bytes;
@@ -574,9 +575,11 @@ struct ecryptfs_open_req {
574 struct list_head kthread_ctl_list; 575 struct list_head kthread_ctl_list;
575}; 576};
576 577
578#define ECRYPTFS_INTERPOSE_FLAG_D_ADD 0x00000001
579#define ECRYPTFS_INTERPOSE_FLAG_DELAY_PERSISTENT_FILE 0x00000002
577int ecryptfs_interpose(struct dentry *hidden_dentry, 580int ecryptfs_interpose(struct dentry *hidden_dentry,
578 struct dentry *this_dentry, struct super_block *sb, 581 struct dentry *this_dentry, struct super_block *sb,
579 int flag); 582 u32 flags);
580int ecryptfs_fill_zeros(struct file *file, loff_t new_length); 583int ecryptfs_fill_zeros(struct file *file, loff_t new_length);
581int ecryptfs_decode_filename(struct ecryptfs_crypt_stat *crypt_stat, 584int ecryptfs_decode_filename(struct ecryptfs_crypt_stat *crypt_stat,
582 const char *name, int length, 585 const char *name, int length,
@@ -709,5 +712,6 @@ void ecryptfs_destroy_kthread(void);
709int ecryptfs_privileged_open(struct file **lower_file, 712int ecryptfs_privileged_open(struct file **lower_file,
710 struct dentry *lower_dentry, 713 struct dentry *lower_dentry,
711 struct vfsmount *lower_mnt); 714 struct vfsmount *lower_mnt);
715int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry);
712 716
713#endif /* #ifndef ECRYPTFS_KERNEL_H */ 717#endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index f0be29051528..2c2d60df3f60 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -199,6 +199,20 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
199 "file must hence be opened RO\n", __func__); 199 "file must hence be opened RO\n", __func__);
200 goto out; 200 goto out;
201 } 201 }
202 if (!ecryptfs_inode_to_private(inode)->lower_file) {
203 BUG_ON(!(crypt_stat->flags & ECRYPTFS_DELAY_PERSISTENT));
204 mutex_lock(&crypt_stat->cs_mutex);
205 crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
206 mutex_unlock(&crypt_stat->cs_mutex);
207 rc = ecryptfs_init_persistent_file(ecryptfs_dentry);
208 if (rc) {
209 printk(KERN_ERR "%s: Error attempting to initialize "
210 "the persistent file for the dentry with name "
211 "[%s]; rc = [%d]\n", __func__,
212 ecryptfs_dentry->d_name.name, rc);
213 goto out;
214 }
215 }
202 ecryptfs_set_file_lower( 216 ecryptfs_set_file_lower(
203 file, ecryptfs_inode_to_private(inode)->lower_file); 217 file, ecryptfs_inode_to_private(inode)->lower_file);
204 if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { 218 if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 7315547193ea..26090878c930 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -308,7 +308,8 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
308 d_add(dentry, NULL); 308 d_add(dentry, NULL);
309 goto out; 309 goto out;
310 } 310 }
311 rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 1); 311 rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb,
312 ECRYPTFS_INTERPOSE_FLAG_D_ADD);
312 if (rc) { 313 if (rc) {
313 ecryptfs_printk(KERN_ERR, "Error interposing\n"); 314 ecryptfs_printk(KERN_ERR, "Error interposing\n");
314 goto out_dput; 315 goto out_dput;
@@ -537,7 +538,8 @@ ecryptfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
537 rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, mode, dev); 538 rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, mode, dev);
538 if (rc || !lower_dentry->d_inode) 539 if (rc || !lower_dentry->d_inode)
539 goto out; 540 goto out;
540 rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0); 541 rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb,
542 ECRYPTFS_INTERPOSE_FLAG_DELAY_PERSISTENT_FILE);
541 if (rc) 543 if (rc)
542 goto out; 544 goto out;
543 fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); 545 fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 10475d93ff53..ee4f84b20410 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -117,7 +117,7 @@ void __ecryptfs_printk(const char *fmt, ...)
117 * 117 *
118 * Returns zero on success; non-zero otherwise 118 * Returns zero on success; non-zero otherwise
119 */ 119 */
120static int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry) 120int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
121{ 121{
122 struct ecryptfs_inode_info *inode_info = 122 struct ecryptfs_inode_info *inode_info =
123 ecryptfs_inode_to_private(ecryptfs_dentry->d_inode); 123 ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
@@ -149,14 +149,14 @@ static int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
149 * @lower_dentry: Existing dentry in the lower filesystem 149 * @lower_dentry: Existing dentry in the lower filesystem
150 * @dentry: ecryptfs' dentry 150 * @dentry: ecryptfs' dentry
151 * @sb: ecryptfs's super_block 151 * @sb: ecryptfs's super_block
152 * @flag: If set to true, then d_add is called, else d_instantiate is called 152 * @flags: flags to govern behavior of interpose procedure
153 * 153 *
154 * Interposes upper and lower dentries. 154 * Interposes upper and lower dentries.
155 * 155 *
156 * Returns zero on success; non-zero otherwise 156 * Returns zero on success; non-zero otherwise
157 */ 157 */
158int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry, 158int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
159 struct super_block *sb, int flag) 159 struct super_block *sb, u32 flags)
160{ 160{
161 struct inode *lower_inode; 161 struct inode *lower_inode;
162 struct inode *inode; 162 struct inode *inode;
@@ -193,7 +193,7 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
193 init_special_inode(inode, lower_inode->i_mode, 193 init_special_inode(inode, lower_inode->i_mode,
194 lower_inode->i_rdev); 194 lower_inode->i_rdev);
195 dentry->d_op = &ecryptfs_dops; 195 dentry->d_op = &ecryptfs_dops;
196 if (flag) 196 if (flags & ECRYPTFS_INTERPOSE_FLAG_D_ADD)
197 d_add(dentry, inode); 197 d_add(dentry, inode);
198 else 198 else
199 d_instantiate(dentry, inode); 199 d_instantiate(dentry, inode);
@@ -201,12 +201,21 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
201 /* This size will be overwritten for real files w/ headers and 201 /* This size will be overwritten for real files w/ headers and
202 * other metadata */ 202 * other metadata */
203 fsstack_copy_inode_size(inode, lower_inode); 203 fsstack_copy_inode_size(inode, lower_inode);
204 rc = ecryptfs_init_persistent_file(dentry); 204 if (!(flags & ECRYPTFS_INTERPOSE_FLAG_DELAY_PERSISTENT_FILE)) {
205 if (rc) { 205 rc = ecryptfs_init_persistent_file(dentry);
206 printk(KERN_ERR "%s: Error attempting to initialize the " 206 if (rc) {
207 "persistent file for the dentry with name [%s]; " 207 printk(KERN_ERR "%s: Error attempting to initialize "
208 "rc = [%d]\n", __func__, dentry->d_name.name, rc); 208 "the persistent file for the dentry with name "
209 goto out; 209 "[%s]; rc = [%d]\n", __func__,
210 dentry->d_name.name, rc);
211 goto out;
212 }
213 } else {
214 struct ecryptfs_inode_info *inode_info =
215 ecryptfs_inode_to_private(dentry->d_inode);
216
217 inode_info->lower_file = NULL;
218 inode_info->crypt_stat.flags |= ECRYPTFS_DELAY_PERSISTENT;
210 } 219 }
211out: 220out:
212 return rc; 221 return rc;