Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F159573763
D23247.id67583.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D23247.id67583.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D23247: Provide O_SEARCH
Attached
Detach File
Event Timeline
Log In to Comment