From 7d2b0bd7d78a05f57adb96cc73a605d05938a037 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 29 Nov 2018 19:13:10 +0000 Subject: [PATCH] If BENEATH is specified, always latch the topping directory vnode. It is possible that we started with a relative path but during the lookup, found an absolute symlink. In this case, BENEATH handling code needs the latch, but it is too late to calculate it. While there, somewhat improve the assertions. Clear the NI_LCF_LATCH flag when the latch vnode is released, so that asserts know the state. Assert that there is a latch if we entered beneath+abs path mode, after the starting point is processed. Reported by: wulf With more input from: pho Sponsored by: The FreeBSD Foundation --- sys/kern/vfs_lookup.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 78893c4f2bd..cb69a75ea65 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -202,8 +202,10 @@ nameicap_cleanup(struct nameidata *ndp, bool clean_latch) vdrop(nt->dp); uma_zfree(nt_zone, nt); } - if (clean_latch && (ndp->ni_lcf & NI_LCF_LATCH) != 0) + if (clean_latch && (ndp->ni_lcf & NI_LCF_LATCH) != 0) { + ndp->ni_lcf &= ~NI_LCF_LATCH; vrele(ndp->ni_beneath_latch); + } } /* @@ -446,7 +448,7 @@ namei(struct nameidata *ndp) if (error == 0 && dp->v_type != VDIR) error = ENOTDIR; } - if (error == 0 && (ndp->ni_lcf & NI_LCF_BENEATH_ABS) != 0) { + if (error == 0 && (cnp->cn_flags & BENEATH) != 0) { if (ndp->ni_dirfd == AT_FDCWD) { ndp->ni_beneath_latch = fdp->fd_cdir; vrefact(ndp->ni_beneath_latch); @@ -471,6 +473,8 @@ namei(struct nameidata *ndp) vrele(dp); goto out; } + MPASS((ndp->ni_lcf & (NI_LCF_BENEATH_ABS | NI_LCF_LATCH)) != + NI_LCF_BENEATH_ABS); if (((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) != 0 && lookup_cap_dotdot != 0) || ((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) == 0 &&