Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys ktrace(9): Fix mutex detection in ktrcsw.



details:   https://anonhg.NetBSD.org/src/rev/ec2c470c8452
branches:  trunk
changeset: 368224:ec2c470c8452
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Wed Jun 29 22:10:43 2022 +0000

description:
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+414edba9d161b7502658%syzkaller.appspotmail.com@localhost
Reported-by: syzbot+4425c97ac717b12495a2%syzkaller.appspotmail.com@localhost
Reported-by: syzbot+5812565b926ee8eb5cf3%syzkaller.appspotmail.com@localhost
Reported-by: syzbot+8b9d7b066c32dbcdc63b%syzkaller.appspotmail.com@localhost
Reported-by: syzbot+909a8e743c967d97f433%syzkaller.appspotmail.com@localhost
Reported-by: syzbot+e2a34bb5509bea0bba11%syzkaller.appspotmail.com@localhost
Reported-by: syzbot+faaea3aad6c9d0829f76%syzkaller.appspotmail.com@localhost

diffstat:

 sys/kern/kern_ktrace.c |  15 ++++++++++-----
 sys/kern/kern_sleepq.c |   9 +++++----
 sys/sys/ktrace.h       |  10 ++++++----
 3 files changed, 21 insertions(+), 13 deletions(-)

diffs (130 lines):

diff -r 2ef096b490c9 -r ec2c470c8452 sys/kern/kern_ktrace.c
--- a/sys/kern/kern_ktrace.c    Wed Jun 29 19:43:46 2022 +0000
+++ b/sys/kern/kern_ktrace.c    Wed Jun 29 22:10:43 2022 +0000
@@ -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 @@
 #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 @@
 }
 
 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 @@
 
        /*
         * 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
diff -r 2ef096b490c9 -r ec2c470c8452 sys/kern/kern_sleepq.c
--- a/sys/kern/kern_sleepq.c    Wed Jun 29 19:43:46 2022 +0000
+++ b/sys/kern/kern_sleepq.c    Wed Jun 29 22:10:43 2022 +0000
@@ -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 @@
        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 @@
                }
        }
 
-       ktrcsw(0, 0);
+       ktrcsw(0, 0, syncobj);
        if (__predict_false(biglocks != 0)) {
                KERNEL_LOCK(biglocks, NULL);
        }
diff -r 2ef096b490c9 -r ec2c470c8452 sys/sys/ktrace.h
--- a/sys/sys/ktrace.h  Wed Jun 29 19:43:46 2022 +0000
+++ b/sys/sys/ktrace.h  Wed Jun 29 22:10:43 2022 +0000
@@ -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 @@
 
 #else
 
+struct syncobj;
+
 void ktrinit(void);
 void ktrderef(struct proc *);
 void ktradref(struct proc *);
@@ -307,7 +309,7 @@
 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 @@
 }
 
 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



Home | Main Index | Thread Index | Old Index