diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 15:14:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 15:14:39 -0400 |
commit | 26b55633a891a28bf04f42882de145eb8e9cb9ad (patch) | |
tree | 997c1bbaad576a0ae4903af59a8d89b86b0f2fae /fs/ecryptfs/inode.c | |
parent | b34d8915c413acb51d837a45fb8747b61f65c020 (diff) | |
parent | 21edad32205e97dc7ccb81a85234c77e760364c8 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ecryptfs/ecryptfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ecryptfs/ecryptfs-2.6:
ecryptfs: dont call lookup_one_len to avoid NULL nameidata
fs/ecryptfs/file.c: introduce missing free
ecryptfs: release reference to lower mount if interpose fails
eCryptfs: Handle ioctl calls with unlocked and compat functions
ecryptfs: Fix warning in ecryptfs_process_response()
Diffstat (limited to 'fs/ecryptfs/inode.c')
-rw-r--r-- | fs/ecryptfs/inode.c | 94 |
1 files changed, 80 insertions, 14 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 82900b063b1..6c55113e722 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -264,7 +264,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | |||
264 | printk(KERN_ERR "%s: Out of memory whilst attempting " | 264 | printk(KERN_ERR "%s: Out of memory whilst attempting " |
265 | "to allocate ecryptfs_dentry_info struct\n", | 265 | "to allocate ecryptfs_dentry_info struct\n", |
266 | __func__); | 266 | __func__); |
267 | goto out_dput; | 267 | goto out_put; |
268 | } | 268 | } |
269 | ecryptfs_set_dentry_lower(ecryptfs_dentry, lower_dentry); | 269 | ecryptfs_set_dentry_lower(ecryptfs_dentry, lower_dentry); |
270 | ecryptfs_set_dentry_lower_mnt(ecryptfs_dentry, lower_mnt); | 270 | ecryptfs_set_dentry_lower_mnt(ecryptfs_dentry, lower_mnt); |
@@ -339,14 +339,85 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | |||
339 | out_free_kmem: | 339 | out_free_kmem: |
340 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); | 340 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); |
341 | goto out; | 341 | goto out; |
342 | out_dput: | 342 | out_put: |
343 | dput(lower_dentry); | 343 | dput(lower_dentry); |
344 | mntput(lower_mnt); | ||
344 | d_drop(ecryptfs_dentry); | 345 | d_drop(ecryptfs_dentry); |
345 | out: | 346 | out: |
346 | return rc; | 347 | return rc; |
347 | } | 348 | } |
348 | 349 | ||
349 | /** | 350 | /** |
351 | * ecryptfs_new_lower_dentry | ||
352 | * @ename: The name of the new dentry. | ||
353 | * @lower_dir_dentry: Parent directory of the new dentry. | ||
354 | * @nd: nameidata from last lookup. | ||
355 | * | ||
356 | * Create a new dentry or get it from lower parent dir. | ||
357 | */ | ||
358 | static struct dentry * | ||
359 | ecryptfs_new_lower_dentry(struct qstr *name, struct dentry *lower_dir_dentry, | ||
360 | struct nameidata *nd) | ||
361 | { | ||
362 | struct dentry *new_dentry; | ||
363 | struct dentry *tmp; | ||
364 | struct inode *lower_dir_inode; | ||
365 | |||
366 | lower_dir_inode = lower_dir_dentry->d_inode; | ||
367 | |||
368 | tmp = d_alloc(lower_dir_dentry, name); | ||
369 | if (!tmp) | ||
370 | return ERR_PTR(-ENOMEM); | ||
371 | |||
372 | mutex_lock(&lower_dir_inode->i_mutex); | ||
373 | new_dentry = lower_dir_inode->i_op->lookup(lower_dir_inode, tmp, nd); | ||
374 | mutex_unlock(&lower_dir_inode->i_mutex); | ||
375 | |||
376 | if (!new_dentry) | ||
377 | new_dentry = tmp; | ||
378 | else | ||
379 | dput(tmp); | ||
380 | |||
381 | return new_dentry; | ||
382 | } | ||
383 | |||
384 | |||
385 | /** | ||
386 | * ecryptfs_lookup_one_lower | ||
387 | * @ecryptfs_dentry: The eCryptfs dentry that we are looking up | ||
388 | * @lower_dir_dentry: lower parent directory | ||
389 | * | ||
390 | * Get the lower dentry from vfs. If lower dentry does not exist yet, | ||
391 | * create it. | ||
392 | */ | ||
393 | static struct dentry * | ||
394 | ecryptfs_lookup_one_lower(struct dentry *ecryptfs_dentry, | ||
395 | struct dentry *lower_dir_dentry) | ||
396 | { | ||
397 | struct nameidata nd; | ||
398 | struct vfsmount *lower_mnt; | ||
399 | struct qstr *name; | ||
400 | int err; | ||
401 | |||
402 | name = &ecryptfs_dentry->d_name; | ||
403 | lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt( | ||
404 | ecryptfs_dentry->d_parent)); | ||
405 | err = vfs_path_lookup(lower_dir_dentry, lower_mnt, name->name , 0, &nd); | ||
406 | mntput(lower_mnt); | ||
407 | |||
408 | if (!err) { | ||
409 | /* we dont need the mount */ | ||
410 | mntput(nd.path.mnt); | ||
411 | return nd.path.dentry; | ||
412 | } | ||
413 | if (err != -ENOENT) | ||
414 | return ERR_PTR(err); | ||
415 | |||
416 | /* create a new lower dentry */ | ||
417 | return ecryptfs_new_lower_dentry(name, lower_dir_dentry, &nd); | ||
418 | } | ||
419 | |||
420 | /** | ||
350 | * ecryptfs_lookup | 421 | * ecryptfs_lookup |
351 | * @ecryptfs_dir_inode: The eCryptfs directory inode | 422 | * @ecryptfs_dir_inode: The eCryptfs directory inode |
352 | * @ecryptfs_dentry: The eCryptfs dentry that we are looking up | 423 | * @ecryptfs_dentry: The eCryptfs dentry that we are looking up |
@@ -373,14 +444,12 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
373 | goto out_d_drop; | 444 | goto out_d_drop; |
374 | } | 445 | } |
375 | lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent); | 446 | lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent); |
376 | mutex_lock(&lower_dir_dentry->d_inode->i_mutex); | 447 | |
377 | lower_dentry = lookup_one_len(ecryptfs_dentry->d_name.name, | 448 | lower_dentry = ecryptfs_lookup_one_lower(ecryptfs_dentry, |
378 | lower_dir_dentry, | 449 | lower_dir_dentry); |
379 | ecryptfs_dentry->d_name.len); | ||
380 | mutex_unlock(&lower_dir_dentry->d_inode->i_mutex); | ||
381 | if (IS_ERR(lower_dentry)) { | 450 | if (IS_ERR(lower_dentry)) { |
382 | rc = PTR_ERR(lower_dentry); | 451 | rc = PTR_ERR(lower_dentry); |
383 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " | 452 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_lower() returned " |
384 | "[%d] on lower_dentry = [%s]\n", __func__, rc, | 453 | "[%d] on lower_dentry = [%s]\n", __func__, rc, |
385 | encrypted_and_encoded_name); | 454 | encrypted_and_encoded_name); |
386 | goto out_d_drop; | 455 | goto out_d_drop; |
@@ -402,14 +471,11 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
402 | "filename; rc = [%d]\n", __func__, rc); | 471 | "filename; rc = [%d]\n", __func__, rc); |
403 | goto out_d_drop; | 472 | goto out_d_drop; |
404 | } | 473 | } |
405 | mutex_lock(&lower_dir_dentry->d_inode->i_mutex); | 474 | lower_dentry = ecryptfs_lookup_one_lower(ecryptfs_dentry, |
406 | lower_dentry = lookup_one_len(encrypted_and_encoded_name, | 475 | lower_dir_dentry); |
407 | lower_dir_dentry, | ||
408 | encrypted_and_encoded_name_size - 1); | ||
409 | mutex_unlock(&lower_dir_dentry->d_inode->i_mutex); | ||
410 | if (IS_ERR(lower_dentry)) { | 476 | if (IS_ERR(lower_dentry)) { |
411 | rc = PTR_ERR(lower_dentry); | 477 | rc = PTR_ERR(lower_dentry); |
412 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " | 478 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_lower() returned " |
413 | "[%d] on lower_dentry = [%s]\n", __func__, rc, | 479 | "[%d] on lower_dentry = [%s]\n", __func__, rc, |
414 | encrypted_and_encoded_name); | 480 | encrypted_and_encoded_name); |
415 | goto out_d_drop; | 481 | goto out_d_drop; |