Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

ipc_pset_signal ignores the kqueue in-flux protocol that knote() implements

Abierto
#166 1 comentario 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
45/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Tranquilo
Stack tecnológico
c

Línea de trabajo

Read sys/kern/kern_event.c, especially knote(), the kqueue_scan() paths around lines 2220 and 2243, and ipc_pset_signal(). First instrument activations where kn_in_flux(kn) is set and KN_SCAN is clear, then reproduce the failure and check the counter. If proceeding with the fix, preserve the KN_SCAN exception and verify the in-flux guard prevents unsafe enqueueing.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

area:mach

Summary

ipc_pset_signal() hand-rolls knote activation and does not implement the
in-flux protocol
that FreeBSD's own knote() implements explicitly. It can
therefore activate and enqueue a knote that the kqueue core has taken out of
the queue and marked in flux — including one that is being dropped and freed.

Found by reading sys/kern/kern_event.c from the base tree (stock
releng/15.1; no patch in patches/ touches it).

The protocol being violated

knote() skips in-flux knotes, and the comment says exactly why the one
exception is safe:

2585	SLIST_FOREACH_SAFE(kn, &list->kl_list, kn_selnext, tkn) {
2586		kq = kn->kn_kq;
2587		KQ_LOCK(kq);
2588		if (kn_in_flux(kn) && (kn->kn_status & KN_SCAN) == 0) {
2589			/*
2590			 * Do not process the influx notes, except for
2591			 * the influx coming from the kq unlock in the
2592			 * kqueue_scan().  In the later case, we do
2593			 * not interfere with the scan, since the code
2594			 * fragment in kqueue_scan() locks the knlist,
2595			 * and cannot proceed until we finished.
2596			 */
2597			KQ_UNLOCK(kq);
2598		}

ipc_pset_signal() has no equivalent. It tests only KN_QUEUED | KN_DISABLED:

(kn)->kn_status |= KN_ACTIVE;
if (((kn)->kn_status & (KN_QUEUED | KN_DISABLED)) == 0)
        mach_knote_enqueue(kn);

Why it cannot simply call knote()

filt_machport() has side effects — it performs the receive into
current_thread()'s ith_* state. Called from knote() on the sender's
thread it would deliver the notification into the wrong thread entirely. That
is presumably why the activation was open-coded. The influx check was not
carried across with it.

Worst case

kqueue_scan()'s EV_ONESHOT path puts a knote in flux without KN_SCAN
and then frees it:

2220	} else if ((kn->kn_flags & EV_ONESHOT) == EV_ONESHOT) {
2221		kn->kn_status &= ~KN_QUEUED;
2222		kn_enter_flux(kn);
2223		kq->kq_count--;
2224		KQ_UNLOCK(kq);
	...
2230		knote_drop(kn, td);

Between 2224 and the drop, ipc_pset_signal() may observe KN_QUEUED clear,
TAILQ_INSERT_TAIL the knote onto kq_head and bump kq_count — on a knote
that is then freed. filt_machport() sets EV_ONESHOT itself on both its
EV_EOF and translate-failure paths, so this is reachable.

A second shape: the zero-return path at 2243 clears KN_QUEUED and
decrements kq_count without a TAILQ_REMOVE, because the knote was
already unlinked when the scan dequeued it. A concurrent re-insertion by
ipc_pset_signal() leaves the knote physically on kq_head while marked
not-queued, with kq_count under-counted.

Relationship to the wedge

Not yet established, and should not be assumed. Every stage of the delivery
path has now measured clean (see #145), so an activation that is dropped or
mis-queued at the kqueue boundary is a live candidate — but three previous
candidates in this area looked equally sound and measured zero.

Instrument before fixing. Count activations landing on a knote with
kn_in_flux(kn) set and KN_SCAN clear — precisely the case knote()
skips. If that counter stays zero while the failure reproduces, this is a
latent correctness bug worth fixing on its own merits but not the wedge.

Fix

Add the same guard knote() uses, keeping the KN_SCAN exception, which is
safe here for the same documented reason: kqueue_scan() holds the knlist
lock across f_event, and ipc_pset_signal() takes that same lock
(ips_note_lock, exclusive via kn_sx_lock on the kqueue side, shared here),
so the two cannot interleave.

Lenguaje dominante
C
Estrellas
12
Forks
3
Merge medio
7 h 1 min
PR fusionados (30 d)
7

Preparar el entorno

Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de nextbsd/nextbsd-kernel

Todos los issues de nextbsd/nextbsd-kernel

Issues similares

Más issues de C

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.