Module Name: src Committed By: riastradh Date: Wed Jun 29 22:27:01 UTC 2022
Modified Files: src/sys/kern: kern_condvar.c kern_sleepq.c kern_synch.c kern_timeout.c kern_turnstile.c sys_lwp.c sys_select.c src/sys/sys: sleepq.h Log Message: sleepq(9): Pass syncobj through to sleepq_block. Previously the usage pattern was: sleepq_enter(sq, l, lock); // locks l ... sleepq_enqueue(sq, ..., sobj, ...); // assumes l locked, sets l_syncobj ... (*) sleepq_block(...); // unlocks l As long as l remains locked from sleepq_enter to sleepq_block, l_syncobj is stable, and sleepq_block uses it via ktrcsw to determine whether the sleep is on a mutex in order to avoid creating ktrace context-switch records (which involves allocation which is forbidden in softint context, while taking and even sleeping for a mutex is allowed). However, in turnstile_block, the logic at (*) also involves turnstile_lendpri, which sometimes unlocks and relocks l. At that point, another thread can swoop in and sleepq_remove l, which sets l_syncobj to sched_syncobj. If that happens, ktrcsw does what is forbidden -- tries to allocate a ktrace record for the context switch. As an optimization, sleepq_block or turnstile_block could stop early if it detects that l_syncobj doesn't match -- we've already been requested to wake up at this point so there's no need to mi_switch. (And then it would be unnecessary to pass the syncobj through sleepq_block, because l_syncobj would remain stable.) But I'll leave that to another change. Reported-by: syzbot+8b9d7b066c32dbcdc...@syzkaller.appspotmail.com To generate a diff of this commit: cvs rdiff -u -r1.53 -r1.54 src/sys/kern/kern_condvar.c cvs rdiff -u -r1.72 -r1.73 src/sys/kern/kern_sleepq.c cvs rdiff -u -r1.350 -r1.351 src/sys/kern/kern_synch.c cvs rdiff -u -r1.69 -r1.70 src/sys/kern/kern_timeout.c cvs rdiff -u -r1.43 -r1.44 src/sys/kern/kern_turnstile.c cvs rdiff -u -r1.82 -r1.83 src/sys/kern/sys_lwp.c cvs rdiff -u -r1.59 -r1.60 src/sys/kern/sys_select.c cvs rdiff -u -r1.34 -r1.35 src/sys/sys/sleepq.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.