diff options
| -rw-r--r-- | fs/namei.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/fs/namei.c b/fs/namei.c index a765e7a741f4..d2783c8a770b 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -414,6 +414,46 @@ do_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
| 414 | } | 414 | } |
| 415 | 415 | ||
| 416 | /* | 416 | /* |
| 417 | * force_reval_path - force revalidation of a dentry | ||
| 418 | * | ||
| 419 | * In some situations the path walking code will trust dentries without | ||
| 420 | * revalidating them. This causes problems for filesystems that depend on | ||
| 421 | * d_revalidate to handle file opens (e.g. NFSv4). When FS_REVAL_DOT is set | ||
| 422 | * (which indicates that it's possible for the dentry to go stale), force | ||
| 423 | * a d_revalidate call before proceeding. | ||
| 424 | * | ||
| 425 | * Returns 0 if the revalidation was successful. If the revalidation fails, | ||
| 426 | * either return the error returned by d_revalidate or -ESTALE if the | ||
| 427 | * revalidation it just returned 0. If d_revalidate returns 0, we attempt to | ||
| 428 | * invalidate the dentry. It's up to the caller to handle putting references | ||
| 429 | * to the path if necessary. | ||
| 430 | */ | ||
| 431 | static int | ||
| 432 | force_reval_path(struct path *path, struct nameidata *nd) | ||
| 433 | { | ||
| 434 | int status; | ||
| 435 | struct dentry *dentry = path->dentry; | ||
| 436 | |||
| 437 | /* | ||
| 438 | * only check on filesystems where it's possible for the dentry to | ||
| 439 | * become stale. It's assumed that if this flag is set then the | ||
| 440 | * d_revalidate op will also be defined. | ||
| 441 | */ | ||
| 442 | if (!(dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)) | ||
| 443 | return 0; | ||
| 444 | |||
| 445 | status = dentry->d_op->d_revalidate(dentry, nd); | ||
| 446 | if (status > 0) | ||
| 447 | return 0; | ||
| 448 | |||
| 449 | if (!status) { | ||
| 450 | d_invalidate(dentry); | ||
| 451 | status = -ESTALE; | ||
| 452 | } | ||
| 453 | return status; | ||
| 454 | } | ||
| 455 | |||
| 456 | /* | ||
| 417 | * Short-cut version of permission(), for calling on directories | 457 | * Short-cut version of permission(), for calling on directories |
| 418 | * during pathname resolution. Combines parts of permission() | 458 | * during pathname resolution. Combines parts of permission() |
| 419 | * and generic_permission(), and tests ONLY for MAY_EXEC permission. | 459 | * and generic_permission(), and tests ONLY for MAY_EXEC permission. |
| @@ -529,6 +569,11 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata | |||
| 529 | error = 0; | 569 | error = 0; |
| 530 | if (s) | 570 | if (s) |
| 531 | error = __vfs_follow_link(nd, s); | 571 | error = __vfs_follow_link(nd, s); |
| 572 | else if (nd->last_type == LAST_BIND) { | ||
| 573 | error = force_reval_path(&nd->path, nd); | ||
| 574 | if (error) | ||
| 575 | path_put(&nd->path); | ||
| 576 | } | ||
| 532 | if (dentry->d_inode->i_op->put_link) | 577 | if (dentry->d_inode->i_op->put_link) |
| 533 | dentry->d_inode->i_op->put_link(dentry, nd, cookie); | 578 | dentry->d_inode->i_op->put_link(dentry, nd, cookie); |
| 534 | } | 579 | } |
