diff options
author | Al Viro <viro@www.linux.org.uk> | 2005-06-06 16:35:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-06 17:42:24 -0400 |
commit | 90ebe5654febe3555a2516d51d3d251226d35fdb (patch) | |
tree | 576e1b58886329a4ea0c8a4b20416ce0dead0e51 | |
parent | 4481e8eea761857367162b0957277d5524fbea63 (diff) |
[PATCH] namei fixes
OK, here comes a patch series that hopefully should close all
too-early-mntput() races in fs/namei.c. Entire area is convoluted as hell, so
I'm splitting that series into _very_ small chunks.
Patches alread in the tree close only (very wide) races in following symlinks
(see "busy inodes after umount" thread some time ago). Unfortunately, quite a
few narrower races of the same nature were not closed. Hopefully this should
take care of all of them.
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/namei.c | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/fs/namei.c b/fs/namei.c index dd78f01b6de8..abeec34e7553 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -493,6 +493,11 @@ fail: | |||
493 | return PTR_ERR(link); | 493 | return PTR_ERR(link); |
494 | } | 494 | } |
495 | 495 | ||
496 | struct path { | ||
497 | struct vfsmount *mnt; | ||
498 | struct dentry *dentry; | ||
499 | }; | ||
500 | |||
496 | static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd) | 501 | static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd) |
497 | { | 502 | { |
498 | int error; | 503 | int error; |
@@ -518,7 +523,7 @@ static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
518 | * Without that kind of total limit, nasty chains of consecutive | 523 | * Without that kind of total limit, nasty chains of consecutive |
519 | * symlinks can cause almost arbitrarily long lookups. | 524 | * symlinks can cause almost arbitrarily long lookups. |
520 | */ | 525 | */ |
521 | static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) | 526 | static inline int do_follow_link(struct path *path, struct nameidata *nd) |
522 | { | 527 | { |
523 | int err = -ELOOP; | 528 | int err = -ELOOP; |
524 | if (current->link_count >= MAX_NESTED_LINKS) | 529 | if (current->link_count >= MAX_NESTED_LINKS) |
@@ -527,13 +532,13 @@ static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
527 | goto loop; | 532 | goto loop; |
528 | BUG_ON(nd->depth >= MAX_NESTED_LINKS); | 533 | BUG_ON(nd->depth >= MAX_NESTED_LINKS); |
529 | cond_resched(); | 534 | cond_resched(); |
530 | err = security_inode_follow_link(dentry, nd); | 535 | err = security_inode_follow_link(path->dentry, nd); |
531 | if (err) | 536 | if (err) |
532 | goto loop; | 537 | goto loop; |
533 | current->link_count++; | 538 | current->link_count++; |
534 | current->total_link_count++; | 539 | current->total_link_count++; |
535 | nd->depth++; | 540 | nd->depth++; |
536 | err = __do_follow_link(dentry, nd); | 541 | err = __do_follow_link(path->dentry, nd); |
537 | current->link_count--; | 542 | current->link_count--; |
538 | nd->depth--; | 543 | nd->depth--; |
539 | return err; | 544 | return err; |
@@ -641,11 +646,6 @@ static inline void follow_dotdot(struct vfsmount **mnt, struct dentry **dentry) | |||
641 | follow_mount(mnt, dentry); | 646 | follow_mount(mnt, dentry); |
642 | } | 647 | } |
643 | 648 | ||
644 | struct path { | ||
645 | struct vfsmount *mnt; | ||
646 | struct dentry *dentry; | ||
647 | }; | ||
648 | |||
649 | /* | 649 | /* |
650 | * It's more convoluted than I'd like it to be, but... it's still fairly | 650 | * It's more convoluted than I'd like it to be, but... it's still fairly |
651 | * small and for now I'd prefer to have fast path as straight as possible. | 651 | * small and for now I'd prefer to have fast path as straight as possible. |
@@ -784,7 +784,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | |||
784 | 784 | ||
785 | if (inode->i_op->follow_link) { | 785 | if (inode->i_op->follow_link) { |
786 | mntget(next.mnt); | 786 | mntget(next.mnt); |
787 | err = do_follow_link(next.dentry, nd); | 787 | err = do_follow_link(&next, nd); |
788 | dput(next.dentry); | 788 | dput(next.dentry); |
789 | mntput(next.mnt); | 789 | mntput(next.mnt); |
790 | if (err) | 790 | if (err) |
@@ -838,7 +838,7 @@ last_component: | |||
838 | if ((lookup_flags & LOOKUP_FOLLOW) | 838 | if ((lookup_flags & LOOKUP_FOLLOW) |
839 | && inode && inode->i_op && inode->i_op->follow_link) { | 839 | && inode && inode->i_op && inode->i_op->follow_link) { |
840 | mntget(next.mnt); | 840 | mntget(next.mnt); |
841 | err = do_follow_link(next.dentry, nd); | 841 | err = do_follow_link(&next, nd); |
842 | dput(next.dentry); | 842 | dput(next.dentry); |
843 | mntput(next.mnt); | 843 | mntput(next.mnt); |
844 | if (err) | 844 | if (err) |