git: 2170bf801d13 - stable/14 - sysctl KERN_PROC_KQUEUE: treat omitted kqfd as request to dump all kqueues

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Mon, 07 Apr 2025 01:29:10 UTC
The branch stable/14 has been updated by kib:

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

commit 2170bf801d13549babf914cffde84b01f44ce604
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2025-03-15 01:50:46 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-04-07 01:28:22 +0000

    sysctl KERN_PROC_KQUEUE: treat omitted kqfd as request to dump all kqueues
    
    (cherry picked from commit ab9b296498fe5809bbb905c320d46e700c267164)
---
 sys/kern/kern_event.c | 64 +++++++++++++++++++++++++++++++--------------------
 1 file changed, 39 insertions(+), 25 deletions(-)

diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 8188323bdbc9..e891cb7c094a 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -2964,8 +2964,6 @@ kern_proc_kqueues_out1(struct thread *td, struct proc *p, struct sbuf *s,
 {
 	struct kern_proc_kqueues_out1_cb_args a;
 
-	MPASS(p == curproc);
-
 	a.s = s;
 	a.compat32 = compat32;
 	return (fget_remote_foreach(td, p, kern_proc_kqueues_out1_cb, &a));
@@ -2987,19 +2985,39 @@ kern_proc_kqueues_out(struct proc *p, struct sbuf *sb, size_t maxlen,
 	return (error);
 }
 
+static int
+sysctl_kern_proc_kqueue_one(struct thread *td, struct sbuf *s, struct proc *p,
+    int kq_fd, bool compat32)
+{
+	struct file *fp;
+	struct kqueue *kq;
+	int error;
+
+	error = fget_remote(td, p, kq_fd, &fp);
+	if (error == 0) {
+		if (fp->f_type != DTYPE_KQUEUE) {
+			error = EINVAL;
+		} else {
+			kq = fp->f_data;
+			error = kern_proc_kqueue_report(s, p, kq_fd, kq,
+			    compat32);
+		}
+		fdrop(fp, td);
+	}
+	return (error);
+}
+
 static int
 sysctl_kern_proc_kqueue(SYSCTL_HANDLER_ARGS)
 {
 	struct thread *td;
 	struct proc *p;
-	struct file *fp;
-	struct kqueue *kq;
 	struct sbuf *s, sm;
-	int error, error1, kq_fd, *name;
+	int error, error1, *name;
 	bool compat32;
 
 	name = (int *)arg1;
-	if ((u_int)arg2 != 2)
+	if ((u_int)arg2 > 2 || (u_int)arg2 == 0)
 		return (EINVAL);
 
 	error = pget((pid_t)name[0], PGET_HOLD | PGET_CANDEBUG, &p);
@@ -3007,36 +3025,32 @@ sysctl_kern_proc_kqueue(SYSCTL_HANDLER_ARGS)
 		return (error);
 
 	td = curthread;
-	kq_fd = name[1];
-	error = fget_remote(td, p, kq_fd, &fp);
-	if (error != 0)
-		goto out1;
-	if (fp->f_type != DTYPE_KQUEUE) {
-		error = EINVAL;
-		goto out2;
-	}
+#ifdef FREEBSD_COMPAT32
+	compat32 = SV_CURPROC_FLAG(SV_ILP32);
+#else
+	compat32 = false;
+#endif
 
 	s = sbuf_new_for_sysctl(&sm, NULL, 0, req);
 	if (s == NULL) {
 		error = ENOMEM;
-		goto out2;
+		goto out;
 	}
 	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, compat32);
+	if ((u_int)arg2 == 1) {
+		error = kern_proc_kqueues_out1(td, p, s, compat32);
+	} else {
+		error = sysctl_kern_proc_kqueue_one(td, s, p,
+		    name[1] /* kq_fd */, compat32);
+	}
+
 	error1 = sbuf_finish(s);
 	if (error == 0)
 		error = error1;
 	sbuf_delete(s);
-out2:
-	fdrop(fp, td);
-out1:
+
+out:
 	PRELE(p);
 	return (error);
 }