diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 3ded2180ac82..be5f8d2774de 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -74,6 +74,9 @@ __FBSDID("$FreeBSD$"); #define NAMEI_DIAGNOSTIC 1 #undef NAMEI_DIAGNOSTIC +FEATURE(rnosymlink, "supports RESOLVE_NO_SYMLINK"); +FEATURE(rbeneath, "supports RESOLVE_BENEATH"); + SDT_PROVIDER_DEFINE(vfs); SDT_PROBE_DEFINE4(vfs, namei, lookup, entry, "struct vnode *", "char *", "unsigned long", "bool"); @@ -1192,6 +1195,11 @@ lookup(struct nameidata *ndp) error = ENOENT; goto bad2; } + if (cnp->cn_flags & RNOSYMLINK) { + /* Linux openat2() behavior for RESOLVE_NO_SYMLINKS */ + error = ELOOP; + goto bad2; + } if (dp->v_mount->mnt_flag & MNT_NOSYMFOLLOW) { error = EACCES; goto bad2; diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index f4274ee38689..fb1f9d31609f 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -201,6 +201,8 @@ open2nameif(int fmode, u_int vn_open_flags) res = ISOPEN | LOCKLEAF; if ((fmode & O_RESOLVE_BENEATH) != 0) res |= RBENEATH; + if ((fmode & O_RESOLVE_NO_SYMLINKS) != 0) + res |= RNOSYMLINK; if ((fmode & O_EMPTY_PATH) != 0) res |= EMPTYPATH; if ((vn_open_flags & VN_OPEN_NOAUDIT) == 0) diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h index 64aa6be3083f..bb6551b47f49 100644 --- a/sys/sys/fcntl.h +++ b/sys/sys/fcntl.h @@ -143,6 +143,7 @@ typedef __pid_t pid_t; #define O_DSYNC 0x01000000 /* POSIX data sync */ #if __BSD_VISIBLE #define O_EMPTY_PATH 0x02000000 +#define O_RESOLVE_NO_SYMLINKS 0x04000000 #endif /* diff --git a/sys/sys/namei.h b/sys/sys/namei.h index d22864a3c2c8..3388e149c4c4 100644 --- a/sys/sys/namei.h +++ b/sys/sys/namei.h @@ -155,6 +155,7 @@ int cache_fplookup(struct nameidata *ndp, enum cache_fpl_status *status, #define LOCKSHARED 0x0100 /* Shared lock leaf */ #define NOFOLLOW 0x0000 /* do not follow symbolic links (pseudo) */ #define RBENEATH 0x100000000ULL /* No escape, even tmp, from start dir */ +#define RNOSYMLINK 0x200000000ULL /* Do not follow any symbolic links */ #define MODMASK 0xf000001ffULL /* mask of operational modifiers */ /*