diff options
author | Tyler Hicks <tyhicks@linux.vnet.ibm.com> | 2011-02-17 19:51:24 -0500 |
---|---|---|
committer | Tyler Hicks <tyhicks@linux.vnet.ibm.com> | 2011-02-17 21:30:29 -0500 |
commit | 8787c7a3e0e3f1aa21856d6b6cd6880cc93497e9 (patch) | |
tree | 5d8e9c0b3ed94c2a584812ae7223c4f72cc3d8ee | |
parent | 85e2efbb1db9a18d218006706d6e4fbeb0216213 (diff) |
eCryptfs: Revert "dont call lookup_one_len to avoid NULL nameidata"
This reverts commit 21edad32205e97dc7ccb81a85234c77e760364c8 and commit
93c3fe40c279f002906ad14584c30671097d4394, which fixed a regression by
the former.
Al Viro pointed out bypassed dcache lookups in
ecryptfs_new_lower_dentry(), misuse of vfs_path_lookup() in
ecryptfs_lookup_one_lower() and a dislike of passing nameidata to the
lower filesystem.
Reported-by: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
-rw-r--r-- | fs/ecryptfs/inode.c | 106 |
1 files changed, 12 insertions, 94 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index bd33f87a1907..fc44823fea3a 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -349,75 +349,6 @@ out: | |||
349 | } | 349 | } |
350 | 350 | ||
351 | /** | 351 | /** |
352 | * ecryptfs_new_lower_dentry | ||
353 | * @name: The name of the new dentry. | ||
354 | * @lower_dir_dentry: Parent directory of the new dentry. | ||
355 | * @nd: nameidata from last lookup. | ||
356 | * | ||
357 | * Create a new dentry or get it from lower parent dir. | ||
358 | */ | ||
359 | static struct dentry * | ||
360 | ecryptfs_new_lower_dentry(struct qstr *name, struct dentry *lower_dir_dentry, | ||
361 | struct nameidata *nd) | ||
362 | { | ||
363 | struct dentry *new_dentry; | ||
364 | struct dentry *tmp; | ||
365 | struct inode *lower_dir_inode; | ||
366 | |||
367 | lower_dir_inode = lower_dir_dentry->d_inode; | ||
368 | |||
369 | tmp = d_alloc(lower_dir_dentry, name); | ||
370 | if (!tmp) | ||
371 | return ERR_PTR(-ENOMEM); | ||
372 | |||
373 | mutex_lock(&lower_dir_inode->i_mutex); | ||
374 | new_dentry = lower_dir_inode->i_op->lookup(lower_dir_inode, tmp, nd); | ||
375 | mutex_unlock(&lower_dir_inode->i_mutex); | ||
376 | |||
377 | if (!new_dentry) | ||
378 | new_dentry = tmp; | ||
379 | else | ||
380 | dput(tmp); | ||
381 | |||
382 | return new_dentry; | ||
383 | } | ||
384 | |||
385 | |||
386 | /** | ||
387 | * ecryptfs_lookup_one_lower | ||
388 | * @ecryptfs_dentry: The eCryptfs dentry that we are looking up | ||
389 | * @lower_dir_dentry: lower parent directory | ||
390 | * @name: lower file name | ||
391 | * | ||
392 | * Get the lower dentry from vfs. If lower dentry does not exist yet, | ||
393 | * create it. | ||
394 | */ | ||
395 | static struct dentry * | ||
396 | ecryptfs_lookup_one_lower(struct dentry *ecryptfs_dentry, | ||
397 | struct dentry *lower_dir_dentry, struct qstr *name) | ||
398 | { | ||
399 | struct nameidata nd; | ||
400 | struct vfsmount *lower_mnt; | ||
401 | int err; | ||
402 | |||
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 | /** | ||
421 | * ecryptfs_lookup | 352 | * ecryptfs_lookup |
422 | * @ecryptfs_dir_inode: The eCryptfs directory inode | 353 | * @ecryptfs_dir_inode: The eCryptfs directory inode |
423 | * @ecryptfs_dentry: The eCryptfs dentry that we are looking up | 354 | * @ecryptfs_dentry: The eCryptfs dentry that we are looking up |
@@ -434,7 +365,6 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
434 | size_t encrypted_and_encoded_name_size; | 365 | size_t encrypted_and_encoded_name_size; |
435 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL; | 366 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL; |
436 | struct dentry *lower_dir_dentry, *lower_dentry; | 367 | struct dentry *lower_dir_dentry, *lower_dentry; |
437 | struct qstr lower_name; | ||
438 | int rc = 0; | 368 | int rc = 0; |
439 | 369 | ||
440 | if ((ecryptfs_dentry->d_name.len == 1 | 370 | if ((ecryptfs_dentry->d_name.len == 1 |
@@ -444,20 +374,14 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
444 | goto out_d_drop; | 374 | goto out_d_drop; |
445 | } | 375 | } |
446 | lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent); | 376 | lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent); |
447 | lower_name.name = ecryptfs_dentry->d_name.name; | 377 | mutex_lock(&lower_dir_dentry->d_inode->i_mutex); |
448 | lower_name.len = ecryptfs_dentry->d_name.len; | 378 | lower_dentry = lookup_one_len(ecryptfs_dentry->d_name.name, |
449 | lower_name.hash = ecryptfs_dentry->d_name.hash; | 379 | lower_dir_dentry, |
450 | if (lower_dir_dentry->d_op && lower_dir_dentry->d_op->d_hash) { | 380 | ecryptfs_dentry->d_name.len); |
451 | rc = lower_dir_dentry->d_op->d_hash(lower_dir_dentry, | 381 | mutex_unlock(&lower_dir_dentry->d_inode->i_mutex); |
452 | lower_dir_dentry->d_inode, &lower_name); | ||
453 | if (rc < 0) | ||
454 | goto out_d_drop; | ||
455 | } | ||
456 | lower_dentry = ecryptfs_lookup_one_lower(ecryptfs_dentry, | ||
457 | lower_dir_dentry, &lower_name); | ||
458 | if (IS_ERR(lower_dentry)) { | 382 | if (IS_ERR(lower_dentry)) { |
459 | rc = PTR_ERR(lower_dentry); | 383 | rc = PTR_ERR(lower_dentry); |
460 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_lower() returned " | 384 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " |
461 | "[%d] on lower_dentry = [%s]\n", __func__, rc, | 385 | "[%d] on lower_dentry = [%s]\n", __func__, rc, |
462 | encrypted_and_encoded_name); | 386 | encrypted_and_encoded_name); |
463 | goto out_d_drop; | 387 | goto out_d_drop; |
@@ -479,20 +403,14 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
479 | "filename; rc = [%d]\n", __func__, rc); | 403 | "filename; rc = [%d]\n", __func__, rc); |
480 | goto out_d_drop; | 404 | goto out_d_drop; |
481 | } | 405 | } |
482 | lower_name.name = encrypted_and_encoded_name; | 406 | mutex_lock(&lower_dir_dentry->d_inode->i_mutex); |
483 | lower_name.len = encrypted_and_encoded_name_size; | 407 | lower_dentry = lookup_one_len(encrypted_and_encoded_name, |
484 | lower_name.hash = full_name_hash(lower_name.name, lower_name.len); | 408 | lower_dir_dentry, |
485 | if (lower_dir_dentry->d_op && lower_dir_dentry->d_op->d_hash) { | 409 | encrypted_and_encoded_name_size); |
486 | rc = lower_dir_dentry->d_op->d_hash(lower_dir_dentry, | 410 | mutex_unlock(&lower_dir_dentry->d_inode->i_mutex); |
487 | lower_dir_dentry->d_inode, &lower_name); | ||
488 | if (rc < 0) | ||
489 | goto out_d_drop; | ||
490 | } | ||
491 | lower_dentry = ecryptfs_lookup_one_lower(ecryptfs_dentry, | ||
492 | lower_dir_dentry, &lower_name); | ||
493 | if (IS_ERR(lower_dentry)) { | 411 | if (IS_ERR(lower_dentry)) { |
494 | rc = PTR_ERR(lower_dentry); | 412 | rc = PTR_ERR(lower_dentry); |
495 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_lower() returned " | 413 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " |
496 | "[%d] on lower_dentry = [%s]\n", __func__, rc, | 414 | "[%d] on lower_dentry = [%s]\n", __func__, rc, |
497 | encrypted_and_encoded_name); | 415 | encrypted_and_encoded_name); |
498 | goto out_d_drop; | 416 | goto out_d_drop; |