Commit 6d7b5aaed7d887b34f29f900244cdbd17a86637c

Authored by Al Viro
1 parent 1d674107ea

namei.c: let follow_link() do put_link() on failure

no need for kludgy "set cookie to ERR_PTR(...) because we failed
before we did actual ->follow_link() and want to suppress put_link()",
no pointless check in put_link() itself.

Callers checked if follow_link() has failed anyway; might as well
break out of their loops if that happened, without bothering
to call put_link() first.

[AV: folded fixes from hch]

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Showing 1 changed file with 41 additions and 33 deletions Side-by-side Diff

... ... @@ -605,7 +605,7 @@
605 605 static inline void put_link(struct nameidata *nd, struct path *link, void *cookie)
606 606 {
607 607 struct inode *inode = link->dentry->d_inode;
608   - if (!IS_ERR(cookie) && inode->i_op->put_link)
  608 + if (inode->i_op->put_link)
609 609 inode->i_op->put_link(link->dentry, nd, cookie);
610 610 path_put(link);
611 611 }
612 612  
613 613  
... ... @@ -613,19 +613,19 @@
613 613 static __always_inline int
614 614 follow_link(struct path *link, struct nameidata *nd, void **p)
615 615 {
616   - int error;
617 616 struct dentry *dentry = link->dentry;
  617 + int error;
  618 + char *s;
618 619  
619 620 BUG_ON(nd->flags & LOOKUP_RCU);
620 621  
621 622 if (link->mnt == nd->path.mnt)
622 623 mntget(link->mnt);
623 624  
624   - if (unlikely(current->total_link_count >= 40)) {
625   - *p = ERR_PTR(-ELOOP); /* no ->put_link(), please */
626   - path_put(&nd->path);
627   - return -ELOOP;
628   - }
  625 + error = -ELOOP;
  626 + if (unlikely(current->total_link_count >= 40))
  627 + goto out_put_nd_path;
  628 +
629 629 cond_resched();
630 630 current->total_link_count++;
631 631  
632 632  
633 633  
634 634  
... ... @@ -633,31 +633,38 @@
633 633 nd_set_link(nd, NULL);
634 634  
635 635 error = security_inode_follow_link(link->dentry, nd);
636   - if (error) {
637   - *p = ERR_PTR(error); /* no ->put_link(), please */
638   - path_put(&nd->path);
639   - return error;
640   - }
  636 + if (error)
  637 + goto out_put_nd_path;
641 638  
642 639 nd->last_type = LAST_BIND;
643 640 *p = dentry->d_inode->i_op->follow_link(dentry, nd);
644 641 error = PTR_ERR(*p);
645   - if (!IS_ERR(*p)) {
646   - char *s = nd_get_link(nd);
647   - error = 0;
648   - if (s)
649   - error = __vfs_follow_link(nd, s);
650   - else if (nd->last_type == LAST_BIND) {
651   - nd->flags |= LOOKUP_JUMPED;
652   - nd->inode = nd->path.dentry->d_inode;
653   - if (nd->inode->i_op->follow_link) {
654   - /* stepped on a _really_ weird one */
655   - path_put(&nd->path);
656   - error = -ELOOP;
657   - }
  642 + if (IS_ERR(*p))
  643 + goto out_put_link;
  644 +
  645 + error = 0;
  646 + s = nd_get_link(nd);
  647 + if (s) {
  648 + error = __vfs_follow_link(nd, s);
  649 + } else if (nd->last_type == LAST_BIND) {
  650 + nd->flags |= LOOKUP_JUMPED;
  651 + nd->inode = nd->path.dentry->d_inode;
  652 + if (nd->inode->i_op->follow_link) {
  653 + /* stepped on a _really_ weird one */
  654 + path_put(&nd->path);
  655 + error = -ELOOP;
658 656 }
659 657 }
  658 + if (unlikely(error))
  659 + put_link(nd, link, *p);
  660 +
660 661 return error;
  662 +
  663 +out_put_nd_path:
  664 + path_put(&nd->path);
  665 +out_put_link:
  666 + path_put(link);
  667 + return error;
661 668 }
662 669  
663 670 static int follow_up_rcu(struct path *path)
... ... @@ -1383,9 +1390,10 @@
1383 1390 void *cookie;
1384 1391  
1385 1392 res = follow_link(&link, nd, &cookie);
1386   - if (!res)
1387   - res = walk_component(nd, path, &nd->last,
1388   - nd->last_type, LOOKUP_FOLLOW);
  1393 + if (res)
  1394 + break;
  1395 + res = walk_component(nd, path, &nd->last,
  1396 + nd->last_type, LOOKUP_FOLLOW);
1389 1397 put_link(nd, &link, cookie);
1390 1398 } while (res > 0);
1391 1399  
... ... @@ -1777,8 +1785,9 @@
1777 1785 struct path link = path;
1778 1786 nd->flags |= LOOKUP_PARENT;
1779 1787 err = follow_link(&link, nd, &cookie);
1780   - if (!err)
1781   - err = lookup_last(nd, &path);
  1788 + if (err)
  1789 + break;
  1790 + err = lookup_last(nd, &path);
1782 1791 put_link(nd, &link, cookie);
1783 1792 }
1784 1793 }
... ... @@ -2475,9 +2484,8 @@
2475 2484 nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
2476 2485 error = follow_link(&link, nd, &cookie);
2477 2486 if (unlikely(error))
2478   - filp = ERR_PTR(error);
2479   - else
2480   - filp = do_last(nd, &path, op, pathname);
  2487 + goto out_filp;
  2488 + filp = do_last(nd, &path, op, pathname);
2481 2489 put_link(nd, &link, cookie);
2482 2490 }
2483 2491 out: