The branch stable/14 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=a66767844690dfd82e14df2d22bd9bc40e46546b
commit a66767844690dfd82e14df2d22bd9bc40e46546b Author: Mark Johnston <ma...@freebsd.org> AuthorDate: 2025-05-28 13:35:24 +0000 Commit: Mark Johnston <ma...@freebsd.org> CommitDate: 2025-06-30 14:19:30 +0000 vfs: Don't clobber namei flags in vn_open_cred() Otherwise NAMEILOOKUP is cleared. More generally it seems quite surprising that the flags set by vn_open_cred() callers are not automatically preserved. Modify open2nameif() such that it takes already-set namei flags into account. Reviewed by: olce, kib Fixes: 7587f6d4840f ("namei: Make stackable filesystems check harder for jail roots") Differential Revision: https://reviews.freebsd.org/D50531 (cherry picked from commit e05e33041c252dc236939683c01ca4b7b083562c) --- sys/kern/vfs_vnops.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index c447ceea1634..c3666ca99c26 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -197,11 +197,11 @@ vn_open(struct nameidata *ndp, int *flagp, int cmode, struct file *fp) } static uint64_t -open2nameif(int fmode, u_int vn_open_flags) +open2nameif(int fmode, u_int vn_open_flags, uint64_t cn_flags) { uint64_t res; - res = ISOPEN | LOCKLEAF; + res = ISOPEN | LOCKLEAF | cn_flags; if ((fmode & O_RESOLVE_BENEATH) != 0) res |= RBENEATH; if ((fmode & O_EMPTY_PATH) != 0) @@ -210,12 +210,17 @@ open2nameif(int fmode, u_int vn_open_flags) res |= OPENREAD; if ((fmode & FWRITE) != 0) res |= OPENWRITE; + if ((fmode & O_NOFOLLOW) != 0) + res &= ~FOLLOW; if ((vn_open_flags & VN_OPEN_NOAUDIT) == 0) res |= AUDITVNODE1; + else + res &= ~AUDITVNODE1; if ((vn_open_flags & VN_OPEN_NOCAPCHECK) != 0) res |= NOCAPCHECK; if ((vn_open_flags & VN_OPEN_WANTIOCTLCAPS) != 0) res |= WANTIOCTLCAPS; + return (res); } @@ -247,7 +252,9 @@ restart: return (EINVAL); else if ((fmode & (O_CREAT | O_DIRECTORY)) == O_CREAT) { ndp->ni_cnd.cn_nameiop = CREATE; - ndp->ni_cnd.cn_flags = open2nameif(fmode, vn_open_flags); + ndp->ni_cnd.cn_flags = open2nameif(fmode, vn_open_flags, + ndp->ni_cnd.cn_flags); + /* * Set NOCACHE to avoid flushing the cache when * rolling in many files at once. @@ -256,8 +263,8 @@ restart: * exist despite NOCACHE. */ ndp->ni_cnd.cn_flags |= LOCKPARENT | NOCACHE | NC_KEEPPOSENTRY; - if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0) - ndp->ni_cnd.cn_flags |= FOLLOW; + if ((fmode & O_EXCL) != 0) + ndp->ni_cnd.cn_flags &= ~FOLLOW; if ((vn_open_flags & VN_OPEN_INVFS) == 0) bwillwrite(); if ((error = namei(ndp)) != 0) @@ -325,9 +332,8 @@ restart: } } else { ndp->ni_cnd.cn_nameiop = LOOKUP; - ndp->ni_cnd.cn_flags = open2nameif(fmode, vn_open_flags); - ndp->ni_cnd.cn_flags |= (fmode & O_NOFOLLOW) != 0 ? NOFOLLOW : - FOLLOW; + ndp->ni_cnd.cn_flags = open2nameif(fmode, vn_open_flags, + ndp->ni_cnd.cn_flags); if ((fmode & FWRITE) == 0) ndp->ni_cnd.cn_flags |= LOCKSHARED; if ((error = namei(ndp)) != 0)