summaryrefslogtreecommitdiff
path: root/sys/kern/kern_timeout.c
diff options
context:
space:
mode:
authorriastradh <riastradh@NetBSD.org>2022-06-29 22:27:01 +0000
committerriastradh <riastradh@NetBSD.org>2022-06-29 22:27:01 +0000
commit1d15b657dfc539a24f6ceeb6894184bf3bc42d64 (patch)
treecc8e254dc68f71cd42c57f80f290b2f7b0362558 /sys/kern/kern_timeout.c
parent4f46ee441c5fd0e1667f385005b453dca450871b (diff)
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+8b9d7b066c32dbcdc63b@syzkaller.appspotmail.com
Diffstat (limited to 'sys/kern/kern_timeout.c')
-rw-r--r--sys/kern/kern_timeout.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c
index 1f78dabfd6e..3d710613b6f 100644
--- a/sys/kern/kern_timeout.c
+++ b/sys/kern/kern_timeout.c
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_timeout.c,v 1.69 2022/03/30 17:02:02 riastradh Exp $ */
+/* $NetBSD: kern_timeout.c,v 1.70 2022/06/29 22:27:01 riastradh Exp $ */
/*-
* Copyright (c) 2003, 2006, 2007, 2008, 2009, 2019 The NetBSD Foundation, Inc.
@@ -59,7 +59,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_timeout.c,v 1.69 2022/03/30 17:02:02 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_timeout.c,v 1.70 2022/06/29 22:27:01 riastradh Exp $");
/*
* Timeouts are kept in a hierarchical timing wheel. The c_time is the
@@ -543,7 +543,7 @@ callout_wait(callout_impl_t *c, void *interlock, kmutex_t *lock)
sleepq_enter(&cc->cc_sleepq, l, cc->cc_lock);
sleepq_enqueue(&cc->cc_sleepq, cc, "callout",
&sleep_syncobj, false);
- sleepq_block(0, false);
+ sleepq_block(0, false, &sleep_syncobj);
}
/*