The branch releng/14.0 has been updated by mjg:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=aaeaba3243354f02a7a7c4ff519efd88edc22572

commit aaeaba3243354f02a7a7c4ff519efd88edc22572
Author:     Olivier Certner <[email protected]>
AuthorDate: 2023-09-22 20:57:20 +0000
Commit:     Mateusz Guzik <[email protected]>
CommitDate: 2023-09-24 21:46:25 +0000

    vfs: fix reference counting/locking on LK_UPGRADE error
    
    Factoring out this code unfortunately introduced reference and lock leaks in
    case of failure in the lock upgrade path under VV_CROSSLOCK. In terms of
    practical use, this impacts unionfs (and nullfs in a corner case).
    
    Fixes:          80bd5ef07025 ("vfs: factor out mount point traversal to a 
dedicated routine")
    MFC after:      3 days
    MFC to:         stable/14 releng/14.0
    Sponsored by:   The FreeBSD Foundation
    Reviewed by:    mjg
    [mjg: massaged the commit message a little bit]
    
    Differential Revision: https://reviews.freebsd.org/D41731
    Approved by:    re (gjb)
    (cherry picked from commit 02cbc029dac936b4ddbc38cef969c4b30c9a7d1f)
    (cherry picked from commit c76dfb929e70c80a2d0280a1371c07738d910c11)
---
 sys/kern/vfs_lookup.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index 151253ffa0f5..d75351c34314 100644
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -905,8 +905,15 @@ vfs_lookup_cross_mount(struct nameidata *ndp)
                                crosslkflags |= LK_EXCLUSIVE | LK_CANRECURSE;
                        } else if ((crosslkflags & LK_EXCLUSIVE) != 0) {
                                error = vn_lock(dp, LK_UPGRADE);
-                               if (error != 0)
+                               if (error != 0) {
+                                       MPASS(error == ENOENT);
+                                       vrele(dp);
+                                       if (dp != ndp->ni_dvp)
+                                               vput(ndp->ni_dvp);
+                                       else
+                                               vrele(ndp->ni_dvp);
                                        break;
+                               }
                                if (dp->v_mountedhere != mp) {
                                        continue;
                                }

Reply via email to