git: fa8fdd80dff9 - main - sysctl KERN_PROC_KQUEUE: implement compat32

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Mon, 24 Mar 2025 02:24:50 UTC
The branch main has been updated by kib:

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

commit fa8fdd80dff94dc848b449282080a5d85a3e6012
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2025-03-13 23:05:21 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-03-24 02:24:14 +0000

    sysctl KERN_PROC_KQUEUE: implement compat32
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D49372
---
 sys/compat/freebsd32/freebsd32.h      | 18 +++++++++++++
 sys/compat/freebsd32/freebsd32_misc.c | 50 +++++++++++++++++++++++++++++++++++
 sys/compat/freebsd32/freebsd32_util.h |  5 ++++
 sys/kern/kern_event.c                 | 38 +++++++++++++++++---------
 4 files changed, 98 insertions(+), 13 deletions(-)

diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h
index 3dbf1b5a876d..2db154a8155c 100644
--- a/sys/compat/freebsd32/freebsd32.h
+++ b/sys/compat/freebsd32/freebsd32.h
@@ -446,6 +446,24 @@ struct kinfo_vm_layout32 {
 	uint32_t	kvm_spare[12];
 };
 
+struct kinfo_knote32 {
+	int		knt_kq_fd;
+	struct kevent32	knt_event;
+	int		knt_status;
+	int		knt_extdata;
+	union {
+		struct {
+			int		knt_vnode_type;
+			uint32_t	knt_vnode_fsid[2];
+			uint32_t	knt_vnode_fileid[2];
+			char		knt_vnode_fullpath[PATH_MAX];
+		} knt_vnode;
+		struct {
+			uint32_t	knt_pipe_ino[2];
+		} knt_pipe;
+	};
+};
+
 struct kld_file_stat_1_32 {
 	int	version;	/* set to sizeof(struct kld_file_stat_1) */
 	char	name[MAXPATHLEN];
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index d54e268f0930..e10f5782c10f 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -709,6 +709,56 @@ freebsd32_kevent_to_kevent32(const struct kevent *kevp, struct kevent32 *ks32)
 	}
 }
 
+void
+freebsd32_kinfo_knote_to_32(const struct kinfo_knote *kin,
+    struct kinfo_knote32 *kin32)
+{
+	memset(kin32, 0, sizeof(*kin32));
+	CP(*kin, *kin32, knt_kq_fd);
+	freebsd32_kevent_to_kevent32(&kin->knt_event, &kin32->knt_event);
+	CP(*kin, *kin32, knt_status);
+	CP(*kin, *kin32, knt_extdata);
+	switch (kin->knt_extdata) {
+	case KNOTE_EXTDATA_NONE:
+		break;
+	case KNOTE_EXTDATA_VNODE:
+		CP(*kin, *kin32, knt_vnode.knt_vnode_type);
+#if BYTE_ORDER == LITTLE_ENDIAN
+		kin32->knt_vnode.knt_vnode_fsid[0] = kin->knt_vnode.
+		    knt_vnode_fsid;
+		kin32->knt_vnode.knt_vnode_fsid[1] = kin->knt_vnode.
+		    knt_vnode_fsid >> 32;
+		kin32->knt_vnode.knt_vnode_fileid[0] = kin->knt_vnode.
+		    knt_vnode_fileid;
+		kin32->knt_vnode.knt_vnode_fileid[1] = kin->knt_vnode.
+		    knt_vnode_fileid >> 32;
+#else
+		kin32->knt_vnode.knt_vnode_fsid[1] = kin->knt_vnode.
+		    knt_vnode_fsid;
+		kin32->knt_vnode.knt_vnode_fsid[0] = kin->knt_vnode.
+		    knt_vnode_fsid >> 32;
+		kin32->knt_vnode.knt_vnode_fileid[1] = kin->knt_vnode.
+		    knt_vnode_fileid;
+		kin32->knt_vnode.knt_vnode_fileid[0] = kin->knt_vnode.
+		    knt_vnode_fileid >> 32;
+#endif
+		memcpy(kin32->knt_vnode.knt_vnode_fullpath,
+		    kin->knt_vnode.knt_vnode_fullpath, PATH_MAX);
+		break;
+	case KNOTE_EXTDATA_PIPE:
+#if BYTE_ORDER == LITTLE_ENDIAN
+		kin32->knt_pipe.knt_pipe_ino[0] = kin->knt_pipe.knt_pipe_ino;
+		kin32->knt_pipe.knt_pipe_ino[1] = kin->knt_pipe.
+		    knt_pipe_ino >> 32;
+#else
+		kin32->knt_pipe.knt_pipe_ino[1] = kin->knt_pipe.knt_pipe_ino;
+		kin32->knt_pipe.knt_pipe_ino[0] = kin->knt_pipe.
+		    knt_pipe_ino >> 32;
+#endif
+		break;
+	}
+}
+
 /*
  * Copy 'count' items into the destination list pointed to by uap->eventlist.
  */
diff --git a/sys/compat/freebsd32/freebsd32_util.h b/sys/compat/freebsd32/freebsd32_util.h
index dca61da714f0..4ac314f4391e 100644
--- a/sys/compat/freebsd32/freebsd32_util.h
+++ b/sys/compat/freebsd32/freebsd32_util.h
@@ -122,6 +122,11 @@ struct image_args;
 int freebsd32_exec_copyin_args(struct image_args *args, const char *fname,
 	    enum uio_seg segflg, uint32_t *argv, uint32_t *envv);
 
+struct kinfo_knote;
+struct kinfo_knote32;
+void	freebsd32_kinfo_knote_to_32(const struct kinfo_knote *kin,
+	    struct kinfo_knote32 *kin32);
+
 extern int compat_freebsd_32bit;
 
 #endif /* !_COMPAT_FREEBSD32_FREEBSD32_UTIL_H_ */
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index e9808e3c6e19..c7260f6bb267 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -75,6 +75,10 @@
 #include <sys/ktrace.h>
 #endif
 #include <machine/atomic.h>
+#ifdef COMPAT_FREEBSD32
+#include <compat/freebsd32/freebsd32.h>
+#include <compat/freebsd32/freebsd32_util.h>
+#endif
 
 #include <vm/uma.h>
 
@@ -2873,9 +2877,12 @@ knote_status_export(int kn_status)
 
 static int
 kern_proc_kqueue_report_one(struct sbuf *s, struct proc *p,
-    int kq_fd, struct kqueue *kq, struct knote *kn)
+    int kq_fd, struct kqueue *kq, struct knote *kn, bool compat32 __unused)
 {
 	struct kinfo_knote kin;
+#ifdef COMPAT_FREEBSD32
+	struct kinfo_knote32 kin32;
+#endif
 	int error;
 
 	if (kn->kn_status == KN_MARKER)
@@ -2889,7 +2896,13 @@ kern_proc_kqueue_report_one(struct sbuf *s, struct proc *p,
 	KQ_UNLOCK_FLUX(kq);
 	if (kn->kn_fop->f_userdump != NULL)
 		(void)kn->kn_fop->f_userdump(p, kn, &kin);
-	error = sbuf_bcat(s, &kin, sizeof(kin));
+#ifdef COMPAT_FREEBSD32
+	if (compat32) {
+		freebsd32_kinfo_knote_to_32(&kin, &kin32);
+		error = sbuf_bcat(s, &kin32, sizeof(kin32));
+	} else
+#endif
+		error = sbuf_bcat(s, &kin, sizeof(kin));
 	KQ_LOCK(kq);
 	kn_leave_flux(kn);
 	return (error);
@@ -2897,7 +2910,7 @@ kern_proc_kqueue_report_one(struct sbuf *s, struct proc *p,
 
 static int
 kern_proc_kqueue_report(struct sbuf *s, struct proc *p, int kq_fd,
-    struct kqueue *kq)
+    struct kqueue *kq, bool compat32)
 {
 	struct knote *kn;
 	int error, i;
@@ -2907,7 +2920,7 @@ kern_proc_kqueue_report(struct sbuf *s, struct proc *p, int kq_fd,
 	for (i = 0; i < kq->kq_knlistsize; i++) {
 		SLIST_FOREACH(kn, &kq->kq_knlist[i], kn_link) {
 			error = kern_proc_kqueue_report_one(s, p, kq_fd,
-			    kq, kn);
+			    kq, kn, compat32);
 			if (error != 0)
 				goto out;
 		}
@@ -2917,7 +2930,7 @@ kern_proc_kqueue_report(struct sbuf *s, struct proc *p, int kq_fd,
 	for (i = 0; i <= kq->kq_knhashmask; i++) {
 		SLIST_FOREACH(kn, &kq->kq_knhash[i], kn_link) {
 			error = kern_proc_kqueue_report_one(s, p, kq_fd,
-			    kq, kn);
+			    kq, kn, compat32);
 			if (error != 0)
 				goto out;
 		}
@@ -2936,6 +2949,7 @@ sysctl_kern_proc_kqueue(SYSCTL_HANDLER_ARGS)
 	struct kqueue *kq;
 	struct sbuf *s, sm;
 	int error, error1, kq_fd, *name;
+	bool compat32;
 
 	name = (int *)arg1;
 	if ((u_int)arg2 != 2)
@@ -2944,13 +2958,6 @@ sysctl_kern_proc_kqueue(SYSCTL_HANDLER_ARGS)
 	error = pget((pid_t)name[0], PGET_HOLD | PGET_CANDEBUG, &p);
 	if (error != 0)
 		return (error);
-#ifdef COMPAT_FREEBSD32
-	if (SV_CURPROC_FLAG(SV_ILP32)) {
-		/* XXXKIB */
-		error = EOPNOTSUPP;
-		goto out1;
-	}
-#endif
 
 	td = curthread;
 	kq_fd = name[1];
@@ -2968,9 +2975,14 @@ sysctl_kern_proc_kqueue(SYSCTL_HANDLER_ARGS)
 		goto out2;
 	}
 	sbuf_clear_flags(s, SBUF_INCLUDENUL);
+#ifdef FREEBSD_COMPAT32
+	compat32 = SV_CURPROC_FLAG(SV_ILP32);
+#else
+	compat32 = false;
+#endif
 
 	kq = fp->f_data;
-	error = kern_proc_kqueue_report(s, p, kq_fd, kq);
+	error = kern_proc_kqueue_report(s, p, kq_fd, kq, compat32);
 	error1 = sbuf_finish(s);
 	if (error == 0)
 		error = error1;