Module Name: src Committed By: riastradh Date: Wed Jun 29 22:10:43 UTC 2022
Modified Files: src/sys/kern: kern_ktrace.c kern_sleepq.c src/sys/sys: ktrace.h Log Message: ktrace(9): Fix mutex detection in ktrcsw. On _entry_ to sleepq_block, l->l_syncobj is set so that ktrcsw (ktr_csw) has the opportunity to detect whether it's a mutex or rwlock. It is critical to avoid ktealloc when we're sleeping on a mutex because we may be in softint context where ktealloc is forbidden. But after mi_switch, on _exit_ from sleepq_block, l->l_syncobj may have been changed back to &sched_syncobj or something by sleepq_remove, and so ktrcsw can no longer rely on l->l_syncobj to determine whether we _were_ sleeping on a mutex or not. Instead, save the syncobj in sleepq_block and pass it through as an argument to ktrcsw. Reported-by: syzbot+414edba9d161b7502...@syzkaller.appspotmail.com Reported-by: syzbot+4425c97ac717b1249...@syzkaller.appspotmail.com Reported-by: syzbot+5812565b926ee8eb5...@syzkaller.appspotmail.com Reported-by: syzbot+8b9d7b066c32dbcdc...@syzkaller.appspotmail.com Reported-by: syzbot+909a8e743c967d97f...@syzkaller.appspotmail.com Reported-by: syzbot+e2a34bb5509bea0bb...@syzkaller.appspotmail.com Reported-by: syzbot+faaea3aad6c9d0829...@syzkaller.appspotmail.com To generate a diff of this commit: cvs rdiff -u -r1.180 -r1.181 src/sys/kern/kern_ktrace.c cvs rdiff -u -r1.71 -r1.72 src/sys/kern/kern_sleepq.c cvs rdiff -u -r1.67 -r1.68 src/sys/sys/ktrace.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/kern_ktrace.c diff -u src/sys/kern/kern_ktrace.c:1.180 src/sys/kern/kern_ktrace.c:1.181 --- src/sys/kern/kern_ktrace.c:1.180 Mon Jun 27 03:56:37 2022 +++ src/sys/kern/kern_ktrace.c Wed Jun 29 22:10:43 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_ktrace.c,v 1.180 2022/06/27 03:56:37 riastradh Exp $ */ +/* $NetBSD: kern_ktrace.c,v 1.181 2022/06/29 22:10:43 riastradh Exp $ */ /*- * Copyright (c) 2006, 2007, 2008, 2020 The NetBSD Foundation, Inc. @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_ktrace.c,v 1.180 2022/06/27 03:56:37 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_ktrace.c,v 1.181 2022/06/29 22:10:43 riastradh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -76,6 +76,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_ktrace. #include <sys/ioctl.h> #include <sys/callout.h> #include <sys/kauth.h> +#include <sys/cpu.h> #include <sys/mount.h> #include <sys/syscallargs.h> @@ -807,7 +808,7 @@ ktr_psig(int sig, sig_t action, const si } void -ktr_csw(int out, int user) +ktr_csw(int out, int user, const struct syncobj *syncobj) { lwp_t *l = curlwp; struct proc *p = l->l_proc; @@ -819,10 +820,14 @@ ktr_csw(int out, int user) /* * Don't record context switches resulting from blocking on - * locks; it's too easy to get duff results. + * locks; the results are not useful, and the mutex may be in a + * softint, which would lead us to ktealloc in softint context, + * which is forbidden. */ - if (l->l_syncobj == &mutex_syncobj || l->l_syncobj == &rw_syncobj) + if (syncobj == &mutex_syncobj || syncobj == &rw_syncobj) return; + KASSERT(!cpu_intr_p()); + KASSERT(!cpu_softintr_p()); /* * We can't sleep if we're already going to sleep (if original Index: src/sys/kern/kern_sleepq.c diff -u src/sys/kern/kern_sleepq.c:1.71 src/sys/kern/kern_sleepq.c:1.72 --- src/sys/kern/kern_sleepq.c:1.71 Fri Apr 8 10:17:55 2022 +++ src/sys/kern/kern_sleepq.c Wed Jun 29 22:10:43 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_sleepq.c,v 1.71 2022/04/08 10:17:55 andvar Exp $ */ +/* $NetBSD: kern_sleepq.c,v 1.72 2022/06/29 22:10:43 riastradh Exp $ */ /*- * Copyright (c) 2006, 2007, 2008, 2009, 2019, 2020 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_sleepq.c,v 1.71 2022/04/08 10:17:55 andvar Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_sleepq.c,v 1.72 2022/06/29 22:10:43 riastradh Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -309,8 +309,9 @@ sleepq_block(int timo, bool catch_p) lwp_t *l = curlwp; bool early = false; int biglocks = l->l_biglocks; + struct syncobj *syncobj = l->l_syncobj; - ktrcsw(1, 0); + ktrcsw(1, 0, syncobj); /* * If sleeping interruptably, check for pending signals, exits or @@ -397,7 +398,7 @@ sleepq_block(int timo, bool catch_p) } } - ktrcsw(0, 0); + ktrcsw(0, 0, syncobj); if (__predict_false(biglocks != 0)) { KERNEL_LOCK(biglocks, NULL); } Index: src/sys/sys/ktrace.h diff -u src/sys/sys/ktrace.h:1.67 src/sys/sys/ktrace.h:1.68 --- src/sys/sys/ktrace.h:1.67 Tue Sep 14 22:01:40 2021 +++ src/sys/sys/ktrace.h Wed Jun 29 22:10:43 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: ktrace.h,v 1.67 2021/09/14 22:01:40 christos Exp $ */ +/* $NetBSD: ktrace.h,v 1.68 2022/06/29 22:10:43 riastradh Exp $ */ /* * Copyright (c) 1988, 1993 @@ -297,6 +297,8 @@ __END_DECLS #else +struct syncobj; + void ktrinit(void); void ktrderef(struct proc *); void ktradref(struct proc *); @@ -307,7 +309,7 @@ extern int ktrace_on; int ktruser(const char *, void *, size_t, int); bool ktr_point(int); -void ktr_csw(int, int); +void ktr_csw(int, int, const struct syncobj *); void ktr_emul(void); void ktr_geniov(int, enum uio_rw, struct iovec *, size_t, int); void ktr_genio(int, enum uio_rw, const void *, size_t, int); @@ -349,10 +351,10 @@ ktrpoint(int fac) } static __inline void -ktrcsw(int a, int b) +ktrcsw(int a, int b, const struct syncobj *c) { if (__predict_false(ktrace_on)) - ktr_csw(a, b); + ktr_csw(a, b, c); } static __inline void