summaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2016-05-04 14:04:13 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2016-05-04 14:04:13 -0400
commit6a480a7842545ec520a91730209ec0bae41694c1 (patch)
treeba40d93639c0cce7e461880199023d371f1b2535 /fs/ecryptfs
parent10c64cea04d3c75c306b3f990586ffb343b63287 (diff)
ecryptfs: fix handling of directory opening
First of all, trying to open them r/w is idiocy; it's guaranteed to fail. Moreover, assigning ->f_pos and assuming that everything will work is blatantly broken - try that with e.g. tmpfs as underlying layer and watch the fireworks. There may be a non-trivial amount of state associated with current IO position, well beyond the numeric offset. Using the single struct file associated with underlying inode is really not a good idea; we ought to open one for each ecryptfs directory struct file. Additionally, file_operations both for directories and non-directories are full of pointless methods; non-directories should *not* have ->iterate(), directories should not have ->flush(), ->fasync() and ->splice_read(). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/ecryptfs')
-rw-r--r--fs/ecryptfs/file.c71
1 files changed, 55 insertions, 16 deletions
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index feef8a9c4de7..f02404052b7b 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -112,7 +112,6 @@ static int ecryptfs_readdir(struct file *file, struct dir_context *ctx)
112 .sb = inode->i_sb, 112 .sb = inode->i_sb,
113 }; 113 };
114 lower_file = ecryptfs_file_to_lower(file); 114 lower_file = ecryptfs_file_to_lower(file);
115 lower_file->f_pos = ctx->pos;
116 rc = iterate_dir(lower_file, &buf.ctx); 115 rc = iterate_dir(lower_file, &buf.ctx);
117 ctx->pos = buf.ctx.pos; 116 ctx->pos = buf.ctx.pos;
118 if (rc < 0) 117 if (rc < 0)
@@ -223,14 +222,6 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
223 } 222 }
224 ecryptfs_set_file_lower( 223 ecryptfs_set_file_lower(
225 file, ecryptfs_inode_to_private(inode)->lower_file); 224 file, ecryptfs_inode_to_private(inode)->lower_file);
226 if (d_is_dir(ecryptfs_dentry)) {
227 ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
228 mutex_lock(&crypt_stat->cs_mutex);
229 crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
230 mutex_unlock(&crypt_stat->cs_mutex);
231 rc = 0;
232 goto out;
233 }
234 rc = read_or_initialize_metadata(ecryptfs_dentry); 225 rc = read_or_initialize_metadata(ecryptfs_dentry);
235 if (rc) 226 if (rc)
236 goto out_put; 227 goto out_put;
@@ -247,6 +238,45 @@ out:
247 return rc; 238 return rc;
248} 239}
249 240
241/**
242 * ecryptfs_dir_open
243 * @inode: inode speciying file to open
244 * @file: Structure to return filled in
245 *
246 * Opens the file specified by inode.
247 *
248 * Returns zero on success; non-zero otherwise
249 */
250static int ecryptfs_dir_open(struct inode *inode, struct file *file)
251{
252 struct dentry *ecryptfs_dentry = file->f_path.dentry;
253 /* Private value of ecryptfs_dentry allocated in
254 * ecryptfs_lookup() */
255 struct ecryptfs_file_info *file_info;
256 struct file *lower_file;
257
258 /* Released in ecryptfs_release or end of function if failure */
259 file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL);
260 ecryptfs_set_file_private(file, file_info);
261 if (unlikely(!file_info)) {
262 ecryptfs_printk(KERN_ERR,
263 "Error attempting to allocate memory\n");
264 return -ENOMEM;
265 }
266 lower_file = dentry_open(ecryptfs_dentry_to_lower_path(ecryptfs_dentry),
267 file->f_flags, current_cred());
268 if (IS_ERR(lower_file)) {
269 printk(KERN_ERR "%s: Error attempting to initialize "
270 "the lower file for the dentry with name "
271 "[%pd]; rc = [%ld]\n", __func__,
272 ecryptfs_dentry, PTR_ERR(lower_file));
273 kmem_cache_free(ecryptfs_file_info_cache, file_info);
274 return PTR_ERR(lower_file);
275 }
276 ecryptfs_set_file_lower(file, lower_file);
277 return 0;
278}
279
250static int ecryptfs_flush(struct file *file, fl_owner_t td) 280static int ecryptfs_flush(struct file *file, fl_owner_t td)
251{ 281{
252 struct file *lower_file = ecryptfs_file_to_lower(file); 282 struct file *lower_file = ecryptfs_file_to_lower(file);
@@ -267,6 +297,19 @@ static int ecryptfs_release(struct inode *inode, struct file *file)
267 return 0; 297 return 0;
268} 298}
269 299
300static int ecryptfs_dir_release(struct inode *inode, struct file *file)
301{
302 fput(ecryptfs_file_to_lower(file));
303 kmem_cache_free(ecryptfs_file_info_cache,
304 ecryptfs_file_to_private(file));
305 return 0;
306}
307
308static loff_t ecryptfs_dir_llseek(struct file *file, loff_t offset, int whence)
309{
310 return vfs_llseek(ecryptfs_file_to_lower(file), offset, whence);
311}
312
270static int 313static int
271ecryptfs_fsync(struct file *file, loff_t start, loff_t end, int datasync) 314ecryptfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
272{ 315{
@@ -346,20 +389,16 @@ const struct file_operations ecryptfs_dir_fops = {
346#ifdef CONFIG_COMPAT 389#ifdef CONFIG_COMPAT
347 .compat_ioctl = ecryptfs_compat_ioctl, 390 .compat_ioctl = ecryptfs_compat_ioctl,
348#endif 391#endif
349 .open = ecryptfs_open, 392 .open = ecryptfs_dir_open,
350 .flush = ecryptfs_flush, 393 .release = ecryptfs_dir_release,
351 .release = ecryptfs_release,
352 .fsync = ecryptfs_fsync, 394 .fsync = ecryptfs_fsync,
353 .fasync = ecryptfs_fasync, 395 .llseek = ecryptfs_dir_llseek,
354 .splice_read = generic_file_splice_read,
355 .llseek = default_llseek,
356}; 396};
357 397
358const struct file_operations ecryptfs_main_fops = { 398const struct file_operations ecryptfs_main_fops = {
359 .llseek = generic_file_llseek, 399 .llseek = generic_file_llseek,
360 .read_iter = ecryptfs_read_update_atime, 400 .read_iter = ecryptfs_read_update_atime,
361 .write_iter = generic_file_write_iter, 401 .write_iter = generic_file_write_iter,
362 .iterate = ecryptfs_readdir,
363 .unlocked_ioctl = ecryptfs_unlocked_ioctl, 402 .unlocked_ioctl = ecryptfs_unlocked_ioctl,
364#ifdef CONFIG_COMPAT 403#ifdef CONFIG_COMPAT
365 .compat_ioctl = ecryptfs_compat_ioctl, 404 .compat_ioctl = ecryptfs_compat_ioctl,