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
This commit is contained in:
Konstantin Belousov 2018-11-29 19:13:10 +00:00
parent fc06a872ec
commit 7d2b0bd7d7
1 changed files with 6 additions and 2 deletions

View File

@ -202,8 +202,10 @@ nameicap_cleanup(struct nameidata *ndp, bool clean_latch)
vdrop(nt->dp); vdrop(nt->dp);
uma_zfree(nt_zone, nt); 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); vrele(ndp->ni_beneath_latch);
}
} }
/* /*
@ -446,7 +448,7 @@ namei(struct nameidata *ndp)
if (error == 0 && dp->v_type != VDIR) if (error == 0 && dp->v_type != VDIR)
error = ENOTDIR; 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) { if (ndp->ni_dirfd == AT_FDCWD) {
ndp->ni_beneath_latch = fdp->fd_cdir; ndp->ni_beneath_latch = fdp->fd_cdir;
vrefact(ndp->ni_beneath_latch); vrefact(ndp->ni_beneath_latch);
@ -471,6 +473,8 @@ namei(struct nameidata *ndp)
vrele(dp); vrele(dp);
goto out; 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 && if (((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) != 0 &&
lookup_cap_dotdot != 0) || lookup_cap_dotdot != 0) ||
((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) == 0 && ((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) == 0 &&