aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h5
-rw-r--r--fs/ecryptfs/file.c22
-rw-r--r--fs/ecryptfs/inode.c30
-rw-r--r--fs/ecryptfs/kthread.c6
-rw-r--r--fs/ecryptfs/main.c72
-rw-r--r--fs/ecryptfs/super.c16
6 files changed, 92 insertions, 59 deletions
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index bd3cafd0949d..380bee1094c3 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -295,6 +295,8 @@ struct ecryptfs_crypt_stat {
295struct ecryptfs_inode_info { 295struct ecryptfs_inode_info {
296 struct inode vfs_inode; 296 struct inode vfs_inode;
297 struct inode *wii_inode; 297 struct inode *wii_inode;
298 struct mutex lower_file_mutex;
299 atomic_t lower_file_count;
298 struct file *lower_file; 300 struct file *lower_file;
299 struct ecryptfs_crypt_stat crypt_stat; 301 struct ecryptfs_crypt_stat crypt_stat;
300}; 302};
@@ -757,7 +759,8 @@ int ecryptfs_privileged_open(struct file **lower_file,
757 struct dentry *lower_dentry, 759 struct dentry *lower_dentry,
758 struct vfsmount *lower_mnt, 760 struct vfsmount *lower_mnt,
759 const struct cred *cred); 761 const struct cred *cred);
760int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry); 762int ecryptfs_get_lower_file(struct dentry *ecryptfs_dentry);
763void ecryptfs_put_lower_file(struct inode *inode);
761int 764int
762ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, 765ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
763 size_t *packet_size, 766 size_t *packet_size,
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index cedc913d11ba..146c4edff70c 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,7 +232,7 @@ 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_ENCRYPTED);
@@ -245,6 +245,8 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
245 "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino, 245 "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino,
246 (unsigned long long)i_size_read(inode)); 246 (unsigned long long)i_size_read(inode));
247 goto out; 247 goto out;
248out_put:
249 ecryptfs_put_lower_file(inode);
248out_free: 250out_free:
249 kmem_cache_free(ecryptfs_file_info_cache, 251 kmem_cache_free(ecryptfs_file_info_cache,
250 ecryptfs_file_to_private(file)); 252 ecryptfs_file_to_private(file));
@@ -254,17 +256,13 @@ out:
254 256
255static int ecryptfs_flush(struct file *file, fl_owner_t td) 257static int ecryptfs_flush(struct file *file, fl_owner_t td)
256{ 258{
257 int rc = 0; 259 return file->f_mode & FMODE_WRITE
258 struct file *lower_file = NULL; 260 ? 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} 261}
265 262
266static int ecryptfs_release(struct inode *inode, struct file *file) 263static int ecryptfs_release(struct inode *inode, struct file *file)
267{ 264{
265 ecryptfs_put_lower_file(inode);
268 kmem_cache_free(ecryptfs_file_info_cache, 266 kmem_cache_free(ecryptfs_file_info_cache,
269 ecryptfs_file_to_private(file)); 267 ecryptfs_file_to_private(file));
270 return 0; 268 return 0;
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 72d357649599..f6b388638c3d 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 }
184out: 183out:
185 return rc; 184 return rc;
186} 185}
@@ -230,7 +229,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
230 struct ecryptfs_crypt_stat *crypt_stat; 229 struct ecryptfs_crypt_stat *crypt_stat;
231 char *page_virt = NULL; 230 char *page_virt = NULL;
232 u64 file_size; 231 u64 file_size;
233 int rc = 0; 232 int put_lower = 0, rc = 0;
234 233
235 lower_dir_dentry = lower_dentry->d_parent; 234 lower_dir_dentry = lower_dentry->d_parent;
236 lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt( 235 lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(
@@ -277,14 +276,15 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
277 rc = -ENOMEM; 276 rc = -ENOMEM;
278 goto out; 277 goto out;
279 } 278 }
280 rc = ecryptfs_init_persistent_file(ecryptfs_dentry); 279 rc = ecryptfs_get_lower_file(ecryptfs_dentry);
281 if (rc) { 280 if (rc) {
282 printk(KERN_ERR "%s: Error attempting to initialize " 281 printk(KERN_ERR "%s: Error attempting to initialize "
283 "the persistent file for the dentry with name " 282 "the lower file for the dentry with name "
284 "[%s]; rc = [%d]\n", __func__, 283 "[%s]; rc = [%d]\n", __func__,
285 ecryptfs_dentry->d_name.name, rc); 284 ecryptfs_dentry->d_name.name, rc);
286 goto out_free_kmem; 285 goto out_free_kmem;
287 } 286 }
287 put_lower = 1;
288 crypt_stat = &ecryptfs_inode_to_private( 288 crypt_stat = &ecryptfs_inode_to_private(
289 ecryptfs_dentry->d_inode)->crypt_stat; 289 ecryptfs_dentry->d_inode)->crypt_stat;
290 /* TODO: lock for crypt_stat comparison */ 290 /* TODO: lock for crypt_stat comparison */
@@ -322,6 +322,8 @@ out_put:
322 mntput(lower_mnt); 322 mntput(lower_mnt);
323 d_drop(ecryptfs_dentry); 323 d_drop(ecryptfs_dentry);
324out: 324out:
325 if (put_lower)
326 ecryptfs_put_lower_file(ecryptfs_dentry->d_inode);
325 return rc; 327 return rc;
326} 328}
327 329
@@ -757,8 +759,11 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
757 759
758 if (unlikely((ia->ia_size == i_size))) { 760 if (unlikely((ia->ia_size == i_size))) {
759 lower_ia->ia_valid &= ~ATTR_SIZE; 761 lower_ia->ia_valid &= ~ATTR_SIZE;
760 goto out; 762 return 0;
761 } 763 }
764 rc = ecryptfs_get_lower_file(dentry);
765 if (rc)
766 return rc;
762 crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; 767 crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
763 /* Switch on growing or shrinking file */ 768 /* Switch on growing or shrinking file */
764 if (ia->ia_size > i_size) { 769 if (ia->ia_size > i_size) {
@@ -836,6 +841,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
836 lower_ia->ia_valid &= ~ATTR_SIZE; 841 lower_ia->ia_valid &= ~ATTR_SIZE;
837 } 842 }
838out: 843out:
844 ecryptfs_put_lower_file(inode);
839 return rc; 845 return rc;
840} 846}
841 847
@@ -911,7 +917,13 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
911 917
912 mount_crypt_stat = &ecryptfs_superblock_to_private( 918 mount_crypt_stat = &ecryptfs_superblock_to_private(
913 dentry->d_sb)->mount_crypt_stat; 919 dentry->d_sb)->mount_crypt_stat;
920 rc = ecryptfs_get_lower_file(dentry);
921 if (rc) {
922 mutex_unlock(&crypt_stat->cs_mutex);
923 goto out;
924 }
914 rc = ecryptfs_read_metadata(dentry); 925 rc = ecryptfs_read_metadata(dentry);
926 ecryptfs_put_lower_file(inode);
915 if (rc) { 927 if (rc) {
916 if (!(mount_crypt_stat->flags 928 if (!(mount_crypt_stat->flags
917 & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { 929 & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
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 */
118int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry) 119static 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); 138int 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
158void 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
143static struct inode *ecryptfs_get_inode(struct inode *lower_inode, 171static 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;
60out: 62out:
@@ -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 */
84static void ecryptfs_destroy_inode(struct inode *inode) 85static 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}