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)

Reply via email to