diff options
Diffstat (limited to 'fs/namei.c')
| -rw-r--r-- | fs/namei.c | 49 |
1 files changed, 42 insertions, 7 deletions
diff --git a/fs/namei.c b/fs/namei.c index 4c4f95ac8aa5..6a82fb7e2127 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -1416,21 +1416,28 @@ static void follow_mount(struct path *path) | |||
| 1416 | } | 1416 | } |
| 1417 | } | 1417 | } |
| 1418 | 1418 | ||
| 1419 | static int path_parent_directory(struct path *path) | ||
| 1420 | { | ||
| 1421 | struct dentry *old = path->dentry; | ||
| 1422 | /* rare case of legitimate dget_parent()... */ | ||
| 1423 | path->dentry = dget_parent(path->dentry); | ||
| 1424 | dput(old); | ||
| 1425 | if (unlikely(!path_connected(path))) | ||
| 1426 | return -ENOENT; | ||
| 1427 | return 0; | ||
| 1428 | } | ||
| 1429 | |||
| 1419 | static int follow_dotdot(struct nameidata *nd) | 1430 | static int follow_dotdot(struct nameidata *nd) |
| 1420 | { | 1431 | { |
| 1421 | while(1) { | 1432 | while(1) { |
| 1422 | struct dentry *old = nd->path.dentry; | ||
| 1423 | |||
| 1424 | if (nd->path.dentry == nd->root.dentry && | 1433 | if (nd->path.dentry == nd->root.dentry && |
| 1425 | nd->path.mnt == nd->root.mnt) { | 1434 | nd->path.mnt == nd->root.mnt) { |
| 1426 | break; | 1435 | break; |
| 1427 | } | 1436 | } |
| 1428 | if (nd->path.dentry != nd->path.mnt->mnt_root) { | 1437 | if (nd->path.dentry != nd->path.mnt->mnt_root) { |
| 1429 | /* rare case of legitimate dget_parent()... */ | 1438 | int ret = path_parent_directory(&nd->path); |
| 1430 | nd->path.dentry = dget_parent(nd->path.dentry); | 1439 | if (ret) |
| 1431 | dput(old); | 1440 | return ret; |
| 1432 | if (unlikely(!path_connected(&nd->path))) | ||
| 1433 | return -ENOENT; | ||
| 1434 | break; | 1441 | break; |
| 1435 | } | 1442 | } |
| 1436 | if (!follow_up(&nd->path)) | 1443 | if (!follow_up(&nd->path)) |
| @@ -2514,6 +2521,34 @@ struct dentry *lookup_one_len_unlocked(const char *name, | |||
| 2514 | } | 2521 | } |
| 2515 | EXPORT_SYMBOL(lookup_one_len_unlocked); | 2522 | EXPORT_SYMBOL(lookup_one_len_unlocked); |
| 2516 | 2523 | ||
| 2524 | #ifdef CONFIG_UNIX98_PTYS | ||
| 2525 | int path_pts(struct path *path) | ||
| 2526 | { | ||
| 2527 | /* Find something mounted on "pts" in the same directory as | ||
| 2528 | * the input path. | ||
| 2529 | */ | ||
| 2530 | struct dentry *child, *parent; | ||
| 2531 | struct qstr this; | ||
| 2532 | int ret; | ||
| 2533 | |||
| 2534 | ret = path_parent_directory(path); | ||
| 2535 | if (ret) | ||
| 2536 | return ret; | ||
| 2537 | |||
| 2538 | parent = path->dentry; | ||
| 2539 | this.name = "pts"; | ||
| 2540 | this.len = 3; | ||
| 2541 | child = d_hash_and_lookup(parent, &this); | ||
| 2542 | if (!child) | ||
| 2543 | return -ENOENT; | ||
| 2544 | |||
| 2545 | path->dentry = child; | ||
| 2546 | dput(parent); | ||
| 2547 | follow_mount(path); | ||
| 2548 | return 0; | ||
| 2549 | } | ||
| 2550 | #endif | ||
| 2551 | |||
| 2517 | int user_path_at_empty(int dfd, const char __user *name, unsigned flags, | 2552 | int user_path_at_empty(int dfd, const char __user *name, unsigned flags, |
| 2518 | struct path *path, int *empty) | 2553 | struct path *path, int *empty) |
| 2519 | { | 2554 | { |
