Page MenuHomeFreeBSD

D23247.id67583.diff
No OneTemporary

D23247.id67583.diff

Index: contrib/netbsd-tests/lib/libc/c063/t_o_search.c
===================================================================
--- contrib/netbsd-tests/lib/libc/c063/t_o_search.c
+++ contrib/netbsd-tests/lib/libc/c063/t_o_search.c
@@ -33,9 +33,10 @@
#include <atf-c.h>
-#include <sys/param.h>
+#include <sys/types.h>
#include <sys/stat.h>
+#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
@@ -50,7 +51,7 @@
* until a decision is reached about the semantics of O_SEARCH and a
* non-broken implementation is available.
*/
-#if (O_MASK & O_SEARCH) != 0
+#if defined(__FreeBSD__) || (O_MASK & O_SEARCH) != 0
#define USE_O_SEARCH
#endif
@@ -257,11 +258,55 @@
int fd;
ATF_REQUIRE(mkdir(DIR, 0755) == 0);
+#ifndef __FreeBSD__
ATF_REQUIRE((dfd = open(FILE, O_CREAT|O_RDWR|O_SEARCH, 0644)) != -1);
+#else
+ ATF_REQUIRE((dfd = open(FILE, O_CREAT|O_SEARCH, 0644)) != -1);
+#endif
ATF_REQUIRE((fd = openat(dfd, BASEFILE, O_RDWR, 0)) == -1);
ATF_REQUIRE(errno == ENOTDIR);
}
+#ifdef USE_O_SEARCH
+ATF_TC(o_search_nord);
+ATF_TC_HEAD(o_search_nord, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "See that openat succeeds with no read permission");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+ATF_TC_BODY(o_search_nord, tc)
+{
+ int dfd, fd;
+
+ ATF_REQUIRE(mkdir(DIR, 0755) == 0);
+ ATF_REQUIRE((fd = open(FILE, O_CREAT|O_RDWR, 0644)) != -1);
+ ATF_REQUIRE(close(fd) == 0);
+
+ ATF_REQUIRE(chmod(DIR, 0100) == 0);
+ ATF_REQUIRE((dfd = open(DIR, O_SEARCH, 0)) != -1);
+
+ ATF_REQUIRE(faccessat(dfd, BASEFILE, W_OK, 0) != -1);
+
+ ATF_REQUIRE(close(dfd) == 0);
+}
+
+ATF_TC(o_search_getdents);
+ATF_TC_HEAD(o_search_getdents, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "See that O_SEARCH forbids getdents");
+}
+ATF_TC_BODY(o_search_getdents, tc)
+{
+ char buf[1024];
+ int dfd;
+
+ ATF_REQUIRE(mkdir(DIR, 0755) == 0);
+ ATF_REQUIRE((dfd = open(DIR, O_SEARCH, 0)) != -1);
+ ATF_REQUIRE(getdents(dfd, buf, sizeof(buf)) < 0);
+ ATF_REQUIRE(close(dfd) == 0);
+}
+#endif /* USE_O_SEARCH */
+
ATF_TP_ADD_TCS(tp)
{
@@ -276,6 +321,10 @@
ATF_TP_ADD_TC(tp, o_search_unpriv_flag2);
#endif
ATF_TP_ADD_TC(tp, o_search_notdir);
+#ifdef USE_O_SEARCH
+ ATF_TP_ADD_TC(tp, o_search_nord);
+ ATF_TP_ADD_TC(tp, o_search_getdents);
+#endif
return atf_no_error();
}
Index: lib/libc/sys/open.2
===================================================================
--- lib/libc/sys/open.2
+++ lib/libc/sys/open.2
@@ -28,7 +28,7 @@
.\" @(#)open.2 8.2 (Berkeley) 11/16/93
.\" $FreeBSD$
.\"
-.Dd September 28, 2019
+.Dd January 31, 2020
.Dt OPEN 2
.Os
.Sh NAME
@@ -166,6 +166,7 @@
O_WRONLY open for writing only
O_RDWR open for reading and writing
O_EXEC open for execute only
+O_SEARCH open for search only
O_NONBLOCK do not block on open
O_APPEND append on each write
O_CREAT create file if it does not exist
@@ -326,6 +327,19 @@
allows arbitrary prefix that ends up at the topping directory,
after which all further resolved components must be under it.
.Pp
+When
+.Fa fd
+is opened with
+.Dv O_SEARCH ,
+execute permissions are checked at open time.
+The
+.Fa fd
+may not be used for any read operations like
+.Xr getdirentries 2 .
+The primary use for this descriptor will be as the lookup descriptor for the
+.Fn *at
+family of functions.
+.Pp
If successful,
.Fn open
returns a non-negative integer, termed a file descriptor.
@@ -518,9 +532,12 @@
of
.Dv O_RDONLY ,
.Dv O_WRONLY ,
-.Dv O_RDWR
+or
+.Dv O_RDWR ,
and
-.Dv O_EXEC .
+.Dv O_EXEC
+or
+.Dv O_SEARCH .
.It Bq Er EBADF
The
.Fa path
Index: lib/libc/tests/c063/Makefile
===================================================================
--- lib/libc/tests/c063/Makefile
+++ lib/libc/tests/c063/Makefile
@@ -1,7 +1,5 @@
# $FreeBSD$
-#TODO: t_o_search
-
NETBSD_ATF_TESTS_C= faccessat_test
NETBSD_ATF_TESTS_C+= fchmodat_test
NETBSD_ATF_TESTS_C+= fchownat_test
@@ -11,6 +9,7 @@
NETBSD_ATF_TESTS_C+= mkdirat_test
NETBSD_ATF_TESTS_C+= mkfifoat_test
NETBSD_ATF_TESTS_C+= mknodat_test
+NETBSD_ATF_TESTS_C+= o_search_test
NETBSD_ATF_TESTS_C+= openat_test
NETBSD_ATF_TESTS_C+= readlinkat_test
NETBSD_ATF_TESTS_C+= renameat_test
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
@@ -1542,7 +1542,9 @@
/*
* Check accessibility of directory.
*/
- if (error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr)) {
+ if ((cnp->cn_flags & NOEXECCHECK) != 0) {
+ cnp->cn_flags &= ~NOEXECCHECK;
+ } else if (error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr)) {
ZFS_EXIT(zfsvfs);
return (error);
}
Index: sys/fs/devfs/devfs_vnops.c
===================================================================
--- sys/fs/devfs/devfs_vnops.c
+++ sys/fs/devfs/devfs_vnops.c
@@ -946,8 +946,9 @@
if ((flags & ISDOTDOT) && (dvp->v_vflag & VV_ROOT))
return (EIO);
- error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td);
- if (error)
+ if ((cnp->cn_flags & NOEXECCHECK) != 0)
+ cnp->cn_flags &= ~NOEXECCHECK;
+ else if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td)) != 0)
return (error);
if (cnp->cn_namelen == 1 && *pname == '.') {
Index: sys/fs/fuse/fuse_vnops.c
===================================================================
--- sys/fs/fuse/fuse_vnops.c
+++ sys/fs/fuse/fuse_vnops.c
@@ -1006,7 +1006,9 @@
if (islastcn && vfs_isrdonly(mp) && (nameiop != LOOKUP))
return EROFS;
- if ((err = fuse_internal_access(dvp, VEXEC, td, cred)))
+ if ((cnp->cn_flags & NOEXECCHECK) != 0)
+ cnp->cn_flags &= ~NOEXECCHECK;
+ else if ((err = fuse_internal_access(dvp, VEXEC, td, cred)))
return err;
if (flags & ISDOTDOT) {
Index: sys/fs/nfsclient/nfs_clvnops.c
===================================================================
--- sys/fs/nfsclient/nfs_clvnops.c
+++ sys/fs/nfsclient/nfs_clvnops.c
@@ -1195,7 +1195,9 @@
}
NFSUNLOCKNODE(np);
- if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td)) != 0)
+ if ((cnp->cn_flags & NOEXECCHECK) != 0)
+ cnp->cn_flags &= ~NOEXECCHECK;
+ else if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td)) != 0)
return (error);
error = cache_lookup(dvp, vpp, cnp, &nctime, &ncticks);
if (error > 0 && error != ENOENT)
Index: sys/fs/smbfs/smbfs_vnops.c
===================================================================
--- sys/fs/smbfs/smbfs_vnops.c
+++ sys/fs/smbfs/smbfs_vnops.c
@@ -1199,7 +1199,9 @@
islastcn = flags & ISLASTCN;
if (islastcn && (mp->mnt_flag & MNT_RDONLY) && (nameiop != LOOKUP))
return EROFS;
- if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td)) != 0)
+ if ((cnp->cn_flags & NOEXECCHECK) != 0)
+ cnp->cn_flags &= ~NOEXECCHECK;
+ else if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td)) != 0)
return error;
smp = VFSTOSMBFS(mp);
dnp = VTOSMB(dvp);
Index: sys/fs/tmpfs/tmpfs_vnops.c
===================================================================
--- sys/fs/tmpfs/tmpfs_vnops.c
+++ sys/fs/tmpfs/tmpfs_vnops.c
@@ -90,9 +90,13 @@
*vpp = NULLVP;
/* Check accessibility of requested node as a first step. */
- error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_thread);
- if (error != 0)
- goto out;
+ if ((cnp->cn_flags & NOEXECCHECK) != 0) {
+ cnp->cn_flags &= ~NOEXECCHECK;
+ } else {
+ error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_thread);
+ if (error != 0)
+ goto out;
+ }
/* We cannot be requesting the parent directory of the root node. */
MPASS(IMPLIES(dnode->tn_type == VDIR &&
Index: sys/kern/vfs_cache.c
===================================================================
--- sys/kern/vfs_cache.c
+++ sys/kern/vfs_cache.c
@@ -2155,8 +2155,9 @@
(cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
return (EROFS);
- error = VOP_ACCESS(dvp, VEXEC, cred, td);
- if (error)
+ if ((flags & NOEXECCHECK) != 0)
+ cnp->cn_flags &= ~NOEXECCHECK;
+ else if ((error = VOP_ACCESS(dvp, VEXEC, cred, td)) != 0)
return (error);
error = cache_lookup(dvp, vpp, cnp, NULL, NULL);
Index: sys/kern/vfs_lookup.c
===================================================================
--- sys/kern/vfs_lookup.c
+++ sys/kern/vfs_lookup.c
@@ -308,6 +308,7 @@
struct vnode *dp; /* the directory we are searching */
struct iovec aiov; /* uio for reading symbolic links */
struct componentname *cnp;
+ struct file *dfp;
struct thread *td;
struct proc *p;
cap_rights_t rights;
@@ -428,10 +429,22 @@
AUDIT_ARG_ATFD1(ndp->ni_dirfd);
if (cnp->cn_flags & AUDITVNODE2)
AUDIT_ARG_ATFD2(ndp->ni_dirfd);
- error = fgetvp_rights(td, ndp->ni_dirfd,
- &rights, &ndp->ni_filecaps, &dp);
- if (error == EINVAL)
+ /*
+ * Effectively inlined fgetvp_rights, because we need to
+ * inspect the file as well as grabbing the vnode.
+ */
+ error = fget_cap_locked(fdp, ndp->ni_dirfd, &rights,
+ &dfp, &ndp->ni_filecaps);
+ if (error != 0 || dfp->f_ops == &badfileops ||
+ dfp->f_vnode == NULL) {
error = ENOTDIR;
+ } else {
+ dp = dfp->f_vnode;
+ vrefact(dp);
+
+ if ((dfp->f_flag & FSEARCH) != 0)
+ cnp->cn_flags |= NOEXECCHECK;
+ }
#ifdef CAPABILITIES
/*
* If file descriptor doesn't have all rights,
Index: sys/sys/fcntl.h
===================================================================
--- sys/sys/fcntl.h
+++ sys/sys/fcntl.h
@@ -119,9 +119,11 @@
#if __POSIX_VISIBLE >= 200809
#define O_DIRECTORY 0x00020000 /* Fail if not directory */
#define O_EXEC 0x00040000 /* Open for execute only */
+#define O_SEARCH O_EXEC
#endif
#ifdef _KERNEL
#define FEXEC O_EXEC
+#define FSEARCH O_SEARCH
#endif
#if __POSIX_VISIBLE >= 200809
Index: sys/sys/namei.h
===================================================================
--- sys/sys/namei.h
+++ sys/sys/namei.h
@@ -161,7 +161,8 @@
#define AUDITVNODE2 0x08000000 /* audit the looked up vnode information */
#define TRAILINGSLASH 0x10000000 /* path ended in a slash */
#define NOCAPCHECK 0x20000000 /* do not perform capability checks */
-#define PARAMASK 0x3ffffe00 /* mask of parameter descriptors */
+#define NOEXECCHECK 0x40000000 /* do not perform exec check on dir */
+#define PARAMASK 0x7ffffe00 /* mask of parameter descriptors */
/*
* Namei results flags

File Metadata

Mime Type
text/plain
Expires
Tue, Jun 16, 7:51 PM (14 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34001927
Default Alt Text
D23247.id67583.diff (10 KB)

Event Timeline