diff options
author | Michael Halcrow <mhalcrow@us.ibm.com> | 2006-10-31 01:07:20 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-31 11:07:01 -0500 |
commit | 45ec4ababe999cb95f9c0cad03b2689cb0b77a2b (patch) | |
tree | 8d2ff3c5c356539bc87777948822741ca488ea6b | |
parent | 316bb95e8ed0ddcd767e8aa54264b6c6190f150c (diff) |
[PATCH] eCryptfs: Fix handling of lower d_count
Fix the use of dget/dput calls to balance out on the lower filesystem.
Signed-off-by: Michael Halcrow <mhalcrow@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/ecryptfs/dentry.c | 8 | ||||
-rw-r--r-- | fs/ecryptfs/inode.c | 62 |
2 files changed, 27 insertions, 43 deletions
diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c index f0d2a433242b..0b9992ab990f 100644 --- a/fs/ecryptfs/dentry.c +++ b/fs/ecryptfs/dentry.c | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | #include <linux/dcache.h> | 25 | #include <linux/dcache.h> |
26 | #include <linux/namei.h> | 26 | #include <linux/namei.h> |
27 | #include <linux/mount.h> | ||
27 | #include "ecryptfs_kernel.h" | 28 | #include "ecryptfs_kernel.h" |
28 | 29 | ||
29 | /** | 30 | /** |
@@ -76,8 +77,13 @@ static void ecryptfs_d_release(struct dentry *dentry) | |||
76 | if (ecryptfs_dentry_to_private(dentry)) | 77 | if (ecryptfs_dentry_to_private(dentry)) |
77 | kmem_cache_free(ecryptfs_dentry_info_cache, | 78 | kmem_cache_free(ecryptfs_dentry_info_cache, |
78 | ecryptfs_dentry_to_private(dentry)); | 79 | ecryptfs_dentry_to_private(dentry)); |
79 | if (lower_dentry) | 80 | if (lower_dentry) { |
81 | struct vfsmount *lower_mnt = | ||
82 | ecryptfs_dentry_to_lower_mnt(dentry); | ||
83 | |||
84 | mntput(lower_mnt); | ||
80 | dput(lower_dentry); | 85 | dput(lower_dentry); |
86 | } | ||
81 | return; | 87 | return; |
82 | } | 88 | } |
83 | 89 | ||
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 2f2c6cf972f7..ff4865d24f0f 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -325,7 +325,6 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, | |||
325 | struct dentry *lower_dir_dentry; | 325 | struct dentry *lower_dir_dentry; |
326 | struct dentry *lower_dentry; | 326 | struct dentry *lower_dentry; |
327 | struct vfsmount *lower_mnt; | 327 | struct vfsmount *lower_mnt; |
328 | struct dentry *tlower_dentry = NULL; | ||
329 | char *encoded_name; | 328 | char *encoded_name; |
330 | unsigned int encoded_namelen; | 329 | unsigned int encoded_namelen; |
331 | struct ecryptfs_crypt_stat *crypt_stat = NULL; | 330 | struct ecryptfs_crypt_stat *crypt_stat = NULL; |
@@ -336,27 +335,32 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, | |||
336 | lower_dir_dentry = ecryptfs_dentry_to_lower(dentry->d_parent); | 335 | lower_dir_dentry = ecryptfs_dentry_to_lower(dentry->d_parent); |
337 | dentry->d_op = &ecryptfs_dops; | 336 | dentry->d_op = &ecryptfs_dops; |
338 | if ((dentry->d_name.len == 1 && !strcmp(dentry->d_name.name, ".")) | 337 | if ((dentry->d_name.len == 1 && !strcmp(dentry->d_name.name, ".")) |
339 | || (dentry->d_name.len == 2 && !strcmp(dentry->d_name.name, ".."))) | 338 | || (dentry->d_name.len == 2 |
340 | goto out_drop; | 339 | && !strcmp(dentry->d_name.name, ".."))) { |
340 | d_drop(dentry); | ||
341 | goto out; | ||
342 | } | ||
341 | encoded_namelen = ecryptfs_encode_filename(crypt_stat, | 343 | encoded_namelen = ecryptfs_encode_filename(crypt_stat, |
342 | dentry->d_name.name, | 344 | dentry->d_name.name, |
343 | dentry->d_name.len, | 345 | dentry->d_name.len, |
344 | &encoded_name); | 346 | &encoded_name); |
345 | if (encoded_namelen < 0) { | 347 | if (encoded_namelen < 0) { |
346 | rc = encoded_namelen; | 348 | rc = encoded_namelen; |
347 | goto out_drop; | 349 | d_drop(dentry); |
350 | goto out; | ||
348 | } | 351 | } |
349 | ecryptfs_printk(KERN_DEBUG, "encoded_name = [%s]; encoded_namelen " | 352 | ecryptfs_printk(KERN_DEBUG, "encoded_name = [%s]; encoded_namelen " |
350 | "= [%d]\n", encoded_name, encoded_namelen); | 353 | "= [%d]\n", encoded_name, encoded_namelen); |
351 | lower_dentry = lookup_one_len(encoded_name, lower_dir_dentry, | 354 | lower_dentry = lookup_one_len(encoded_name, lower_dir_dentry, |
352 | encoded_namelen - 1); | 355 | encoded_namelen - 1); |
353 | kfree(encoded_name); | 356 | kfree(encoded_name); |
354 | lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); | ||
355 | if (IS_ERR(lower_dentry)) { | 357 | if (IS_ERR(lower_dentry)) { |
356 | ecryptfs_printk(KERN_ERR, "ERR from lower_dentry\n"); | 358 | ecryptfs_printk(KERN_ERR, "ERR from lower_dentry\n"); |
357 | rc = PTR_ERR(lower_dentry); | 359 | rc = PTR_ERR(lower_dentry); |
358 | goto out_drop; | 360 | d_drop(dentry); |
361 | goto out; | ||
359 | } | 362 | } |
363 | lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); | ||
360 | ecryptfs_printk(KERN_DEBUG, "lower_dentry = [%p]; lower_dentry->" | 364 | ecryptfs_printk(KERN_DEBUG, "lower_dentry = [%p]; lower_dentry->" |
361 | "d_name.name = [%s]\n", lower_dentry, | 365 | "d_name.name = [%s]\n", lower_dentry, |
362 | lower_dentry->d_name.name); | 366 | lower_dentry->d_name.name); |
@@ -397,12 +401,6 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, | |||
397 | "as we *think* we are about to unlink\n"); | 401 | "as we *think* we are about to unlink\n"); |
398 | goto out; | 402 | goto out; |
399 | } | 403 | } |
400 | tlower_dentry = dget(lower_dentry); | ||
401 | if (!tlower_dentry || IS_ERR(tlower_dentry)) { | ||
402 | rc = -ENOMEM; | ||
403 | ecryptfs_printk(KERN_ERR, "Cannot dget lower_dentry\n"); | ||
404 | goto out_dput; | ||
405 | } | ||
406 | /* Released in this function */ | 404 | /* Released in this function */ |
407 | page_virt = | 405 | page_virt = |
408 | (char *)kmem_cache_alloc(ecryptfs_header_cache_2, | 406 | (char *)kmem_cache_alloc(ecryptfs_header_cache_2, |
@@ -414,7 +412,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, | |||
414 | goto out_dput; | 412 | goto out_dput; |
415 | } | 413 | } |
416 | memset(page_virt, 0, PAGE_CACHE_SIZE); | 414 | memset(page_virt, 0, PAGE_CACHE_SIZE); |
417 | rc = ecryptfs_read_header_region(page_virt, tlower_dentry, nd->mnt); | 415 | rc = ecryptfs_read_header_region(page_virt, lower_dentry, nd->mnt); |
418 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; | 416 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; |
419 | if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) | 417 | if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) |
420 | ecryptfs_set_default_sizes(crypt_stat); | 418 | ecryptfs_set_default_sizes(crypt_stat); |
@@ -437,9 +435,6 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, | |||
437 | 435 | ||
438 | out_dput: | 436 | out_dput: |
439 | dput(lower_dentry); | 437 | dput(lower_dentry); |
440 | if (tlower_dentry) | ||
441 | dput(tlower_dentry); | ||
442 | out_drop: | ||
443 | d_drop(dentry); | 438 | d_drop(dentry); |
444 | out: | 439 | out: |
445 | return ERR_PTR(rc); | 440 | return ERR_PTR(rc); |
@@ -475,8 +470,8 @@ out_lock: | |||
475 | unlock_dir(lower_dir_dentry); | 470 | unlock_dir(lower_dir_dentry); |
476 | dput(lower_new_dentry); | 471 | dput(lower_new_dentry); |
477 | dput(lower_old_dentry); | 472 | dput(lower_old_dentry); |
478 | if (!new_dentry->d_inode) | 473 | d_drop(new_dentry); |
479 | d_drop(new_dentry); | 474 | d_drop(old_dentry); |
480 | return rc; | 475 | return rc; |
481 | } | 476 | } |
482 | 477 | ||
@@ -565,41 +560,24 @@ out: | |||
565 | 560 | ||
566 | static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) | 561 | static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) |
567 | { | 562 | { |
568 | int rc = 0; | ||
569 | struct dentry *tdentry = NULL; | ||
570 | struct dentry *lower_dentry; | 563 | struct dentry *lower_dentry; |
571 | struct dentry *tlower_dentry = NULL; | ||
572 | struct dentry *lower_dir_dentry; | 564 | struct dentry *lower_dir_dentry; |
565 | int rc; | ||
573 | 566 | ||
574 | lower_dentry = ecryptfs_dentry_to_lower(dentry); | 567 | lower_dentry = ecryptfs_dentry_to_lower(dentry); |
575 | if (!(tdentry = dget(dentry))) { | 568 | dget(dentry); |
576 | rc = -EINVAL; | ||
577 | ecryptfs_printk(KERN_ERR, "Error dget'ing dentry [%p]\n", | ||
578 | dentry); | ||
579 | goto out; | ||
580 | } | ||
581 | lower_dir_dentry = lock_parent(lower_dentry); | 569 | lower_dir_dentry = lock_parent(lower_dentry); |
582 | if (!(tlower_dentry = dget(lower_dentry))) { | 570 | dget(lower_dentry); |
583 | rc = -EINVAL; | ||
584 | ecryptfs_printk(KERN_ERR, "Error dget'ing lower_dentry " | ||
585 | "[%p]\n", lower_dentry); | ||
586 | goto out; | ||
587 | } | ||
588 | rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); | 571 | rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); |
589 | if (!rc) { | 572 | dput(lower_dentry); |
590 | d_delete(tlower_dentry); | 573 | if (!rc) |
591 | tlower_dentry = NULL; | 574 | d_delete(lower_dentry); |
592 | } | ||
593 | ecryptfs_copy_attr_times(dir, lower_dir_dentry->d_inode); | 575 | ecryptfs_copy_attr_times(dir, lower_dir_dentry->d_inode); |
594 | dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; | 576 | dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; |
595 | unlock_dir(lower_dir_dentry); | 577 | unlock_dir(lower_dir_dentry); |
596 | if (!rc) | 578 | if (!rc) |
597 | d_drop(dentry); | 579 | d_drop(dentry); |
598 | out: | 580 | dput(dentry); |
599 | if (tdentry) | ||
600 | dput(tdentry); | ||
601 | if (tlower_dentry) | ||
602 | dput(tlower_dentry); | ||
603 | return rc; | 581 | return rc; |
604 | } | 582 | } |
605 | 583 | ||