From a718431c30a57226bc7c1a9181fc84bab00641a1 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 24 Apr 2023 02:21:42 +0300 Subject: [PATCH] lookup(): ensure that openat("/", "..", O_RESOLVE_BENEATH) fails PR: 269780 Reported by: Dan Gohman Reviewed by: emaste, markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D39773 --- sys/kern/vfs_lookup.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index d9a9cabde177..66a8b267f346 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -1083,12 +1083,16 @@ vfs_lookup(struct nameidata *ndp) pr = pr->pr_parent) if (dp == pr->pr_root) break; - if (dp == ndp->ni_rootdir || - dp == ndp->ni_topdir || - dp == rootvnode || - pr != NULL || - ((dp->v_vflag & VV_ROOT) != 0 && - (cnp->cn_flags & NOCROSSMOUNT) != 0)) { + bool isroot = dp == ndp->ni_rootdir || + dp == ndp->ni_topdir || dp == rootvnode || + pr != NULL; + if (isroot && (ndp->ni_lcf & + NI_LCF_STRICTRELATIVE) != 0) { + error = ENOTCAPABLE; + goto capdotdot; + } + if (isroot || ((dp->v_vflag & VV_ROOT) != 0 && + (cnp->cn_flags & NOCROSSMOUNT) != 0)) { ndp->ni_dvp = dp; ndp->ni_vp = dp; VREF(dp); @@ -1109,6 +1113,7 @@ vfs_lookup(struct nameidata *ndp) LK_RETRY, ISDOTDOT)); error = nameicap_check_dotdot(ndp, dp); if (error != 0) { +capdotdot: #ifdef KTRACE if (KTRPOINT(curthread, KTR_CAPFAIL)) ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL);