git: 78df5deaf5f1 - releng/15.1 - kqueue: Fix handling of marker knotes during fork
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 29 Sep 2026 16:00:03 UTC
The branch releng/15.1 has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=78df5deaf5f120221cf2965346bb5f23d1d1ab72
commit 78df5deaf5f120221cf2965346bb5f23d1d1ab72
Author: Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-09-28 13:40:45 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-09-29 01:01:48 +0000
kqueue: Fix handling of marker knotes during fork
Commit d8bdcb08d0eb fixed a problem in kqueue_fork_copy_knote() where we
did not skip over marker knotes when copying. However, that fix was not
sufficient: we bump the influx counter and check for a marker after
dropping the kqueue lock. So, if multiple threads in a process are
forking concurrently, kqueue_fork_copy_list() may mark a marker as
in-flux and drop the lock; if the marker owner then frees the marker,
the first thread will decrement the in-flux counter of a freed knotes.
This use-after-free can be exploited, at least prior to commit
d8bdcb08d0eb, which makes exploitation more challenging.
Approved by: so
Security: FreeBSD-SA-26:65.kqueue
Security: CVE-2026-58099
Reported by: Reo Shiseki
Reviewed by: kib
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D59522
---
sys/kern/kern_event.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 706f0e6d658e..ec9036bd30de 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -3085,9 +3085,9 @@ kqueue_fork_copy_knote(struct kqueue *kq, struct kqueue *kq1, struct knote *kn,
("%s: knote %p not in flux", __func__, kn));
KASSERT((kn->kn_status & KN_DETACHED) == 0,
("%s: knote %p not detached", __func__, kn));
+ KASSERT((kn->kn_status & KN_MARKER) == 0,
+ ("%s: knote %p not detached", __func__, kn));
- if ((kn->kn_status & KN_MARKER) != 0)
- return;
if ((kn->kn_status & KN_KQUEUE) != 0) {
/*
* We cannot hold references to a kqueue outside of the process
@@ -3153,7 +3153,7 @@ kqueue_fork_copy_list(struct klist *knlist, struct knote *marker,
kn = SLIST_FIRST(knlist);
while (kn != NULL) {
MPASS(kn->kn_kq == kq);
- if ((kn->kn_status & KN_DETACHED) != 0 ||
+ if ((kn->kn_status & (KN_DETACHED | KN_MARKER)) != 0 ||
(kn_in_flux(kn) && (kn->kn_status & KN_SCAN) == 0)) {
kn = SLIST_NEXT(kn, kn_link);
continue;