ipc_pset_signal ignores the kqueue in-flux protocol that knote() implements
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 45/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Tranquilla
- Stack tecnologico
- c
- Ambito
- operating-systems
Direzione di ricerca
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.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
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.
- Lingua principale
- C
- Stelle
- 12
- Fork
- 3
- Merge medio
- 1h 33m
- PR unite (30g)
- 58
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di nextbsd/nextbsd-kernel
-
area:bluetooth bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
nextbsd/nextbsd-kernel#236 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
area:vm bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
nextbsd/nextbsd-kernel#226 ·
I maintainer di solito rispondono entro 1 giorno
-
area:network enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
nextbsd/nextbsd-kernel#53 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
area:kext enhancement
Difficoltà 4/5 3-5 giorni Idoneità per principianti 52/100
nextbsd/nextbsd-kernel#329 ·
I maintainer di solito rispondono entro 1 giorno
-
area:kext enhancement
Difficoltà 3/5 1-2 giorni Idoneità per principianti 57/100
nextbsd/nextbsd-kernel#328 ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di nextbsd/nextbsd-kernel
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
-
priority:medium type:chore
Difficoltà 1/5 1-3 ore Idoneità per principianti 84/100
crazy-goat/php-fpm-ng#1041 ·
I maintainer di solito rispondono entro 1 giorno
-
Bug Status: Needs Triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
Test failure on FreeBSD: #26 unexpected system_clock sourceForse già presa Una pull request collegata a questa issue è aperta o già unita. Apertalow priority rt_lib tests
Difficoltà 2/5 1-3 ore Idoneità per principianti 67/100
I maintainer di solito rispondono entro 1 giorno