Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 15 Apr 2021 09:50:09 GMT
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: bbf7a4e878ed - main - O_PATH: allow vnode kevent filter on such files
Message-ID:  <202104150950.13F9o9Sx069518@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=bbf7a4e878ed6828d13c7029c128a7e60dc25391

commit bbf7a4e878ed6828d13c7029c128a7e60dc25391
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2021-04-07 18:31:48 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2021-04-15 09:49:18 +0000

    O_PATH: allow vnode kevent filter on such files
    
    if VREAD access is checked as allowed during open
    
    Requested by:   wulf
    Reviewed by:    markj
    Tested by:      pho
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D29323
---
 lib/libc/sys/open.2     |  3 +++
 sys/kern/kern_descrip.c |  2 +-
 sys/kern/vfs_syscalls.c |  3 ++-
 sys/kern/vfs_vnops.c    | 14 +++++++++++++-
 sys/sys/fcntl.h         |  2 ++
 sys/sys/file.h          |  1 +
 6 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/lib/libc/sys/open.2 b/lib/libc/sys/open.2
index 06a877e34460..a7806df69daf 100644
--- a/lib/libc/sys/open.2
+++ b/lib/libc/sys/open.2
@@ -342,6 +342,9 @@ can be passed over a
 socket using a
 .Dv SCM_RIGHTS
 message
+.It Xr kqueue 2
+using for
+.Dv EVFILT_VNODE
 .El
 But operations like
 .Xr read 2 ,
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index a28e94634326..30ac40ffe296 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -4988,7 +4988,7 @@ struct fileops path_fileops = {
 	.fo_truncate = badfo_truncate,
 	.fo_ioctl = badfo_ioctl,
 	.fo_poll = path_poll,
-	.fo_kqfilter = badfo_kqfilter,
+	.fo_kqfilter = vn_kqfilter_opath,
 	.fo_stat = vn_statfile,
 	.fo_close = path_close,
 	.fo_chmod = badfo_chmod,
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 9130843f6761..43104a472b5b 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1192,7 +1192,8 @@ kern_openat(struct thread *td, int fd, const char *path, enum uio_seg pathseg,
 		KASSERT(vp->v_type != VFIFO || (flags & O_PATH) != 0,
 		    ("Unexpected fifo fp %p vp %p", fp, vp));
 		if ((flags & O_PATH) != 0) {
-			finit_vnode(fp, flags, NULL, &path_fileops);
+			finit(fp, (flags & FMASK) | (fp->f_flag & FKQALLOWED),
+			    DTYPE_VNODE, NULL, &path_fileops);
 			vhold(vp);
 			vunref(vp);
 		} else {
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index bb9ee2cceb79..9da35721def4 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -426,8 +426,12 @@ vn_open_vnode(struct vnode *vp, int fmode, struct ucred *cred,
 		if (error != 0)
 			return (error);
 	}
-	if ((fmode & O_PATH) != 0)
+	if ((fmode & O_PATH) != 0) {
+		error = VOP_ACCESS(vp, VREAD, cred, td);
+		if (error == 0)
+			fp->f_flag |= FKQALLOWED;
 		return (0);
+	}
 
 	if (vp->v_type == VFIFO && VOP_ISLOCKED(vp) != LK_EXCLUSIVE)
 		vn_lock(vp, LK_UPGRADE | LK_RETRY);
@@ -2139,6 +2143,14 @@ vn_kqfilter(struct file *fp, struct knote *kn)
 	return (VOP_KQFILTER(fp->f_vnode, kn));
 }
 
+int
+vn_kqfilter_opath(struct file *fp, struct knote *kn)
+{
+	if ((fp->f_flag & FKQALLOWED) == 0)
+		return (EBADF);
+	return (vn_kqfilter(fp, kn));
+}
+
 /*
  * Simplified in-kernel wrapper calls for extended attribute access.
  * Both calls pass in a NULL credential, authorizing as "kernel" access.
diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h
index c328abaa02af..58d46ae26338 100644
--- a/sys/sys/fcntl.h
+++ b/sys/sys/fcntl.h
@@ -153,6 +153,8 @@ typedef	__pid_t		pid_t;
 #define	FREVOKE		O_VERIFY
 /* Only for fo_close() from half-succeeded open */
 #define	FOPENFAILED	O_TTY_INIT
+/* Only for O_PATH files which passed ACCESS FREAD check on open */
+#define	FKQALLOWED	O_RESOLVE_BENEATH
 
 /* convert from open() flags to/from fflags; convert O_RD/WR to FREAD/FWRITE */
 #define	FFLAGS(oflags)	((oflags) & O_EXEC ? (oflags) : (oflags) + 1)
diff --git a/sys/sys/file.h b/sys/sys/file.h
index 9237ee5ceb9d..b16e23bdfbcf 100644
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -267,6 +267,7 @@ fo_stat_t	vn_statfile;
 fo_sendfile_t	vn_sendfile;
 fo_seek_t	vn_seek;
 fo_fill_kinfo_t	vn_fill_kinfo;
+fo_kqfilter_t	vn_kqfilter_opath;
 int vn_fill_kinfo_vnode(struct vnode *vp, struct kinfo_file *kif);
 
 void finit(struct file *, u_int, short, void *, struct fileops *);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202104150950.13F9o9Sx069518>