From f8f7dc1f1132b5aeb0dfc6c92da9ba96b923f6b9 Mon Sep 17 00:00:00 2001 From: bluhm Date: Wed, 25 Sep 2024 18:24:13 +0000 Subject: [PATCH] Do not crash in witness code if interrupt fires early. It can happen that an interrupt handler is called immediately on a secondary CPU when it is spun up during boot. At that moment no process is schduled yet, so curproc is NULL. To prevent a crash when p->p_sleeplocks is dereferenced, skip witness check in this case. OK visa@ --- sys/kern/subr_witness.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c index 9f0919013b2..7110414f25c 100644 --- a/sys/kern/subr_witness.c +++ b/sys/kern/subr_witness.c @@ -1,4 +1,4 @@ -/* $OpenBSD: subr_witness.c,v 1.53 2024/06/03 14:34:19 claudio Exp $ */ +/* $OpenBSD: subr_witness.c,v 1.54 2024/09/25 18:24:13 bluhm Exp $ */ /*- * Copyright (c) 2008 Isilon Systems, Inc. @@ -766,7 +766,6 @@ witness_checkorder(struct lock_object *lock, int flags, struct lock_list_entry *lock_list, *lle; struct lock_instance *lock1, *lock2, *plock; struct lock_class *class, *iclass; - struct proc *p; struct witness *w, *w1; int i, j, s; @@ -792,9 +791,9 @@ witness_checkorder(struct lock_object *lock, int flags, w = lock->lo_witness = enroll(lock->lo_type, lock->lo_name, class); - p = curproc; - if (class->lc_flags & LC_SLEEPLOCK) { + struct proc *p; + /* * Since spin locks include a critical section, this check * implicitly enforces a lock order of all sleep locks before @@ -811,6 +810,9 @@ witness_checkorder(struct lock_object *lock, int flags, * If this is the first lock acquired then just return as * no order checking is needed. */ + p = curproc; + if (p == NULL) + return; lock_list = p->p_sleeplocks; if (lock_list == NULL || lock_list->ll_count == 0) return; @@ -1097,7 +1099,6 @@ witness_lock(struct lock_object *lock, int flags) { struct lock_list_entry **lock_list, *lle; struct lock_instance *instance; - struct proc *p; struct witness *w; int s; @@ -1110,12 +1111,15 @@ witness_lock(struct lock_object *lock, int flags) w = lock->lo_witness = enroll(lock->lo_type, lock->lo_name, LOCK_CLASS(lock)); - p = curproc; - /* Determine lock list for this lock. */ - if (LOCK_CLASS(lock)->lc_flags & LC_SLEEPLOCK) + if (LOCK_CLASS(lock)->lc_flags & LC_SLEEPLOCK) { + struct proc *p; + + p = curproc; + if (p == NULL) + return; lock_list = &p->p_sleeplocks; - else + } else lock_list = &witness_cpu[cpu_number()].wc_spinlocks; s = splhigh(); @@ -1243,20 +1247,23 @@ witness_unlock(struct lock_object *lock, int flags) struct lock_list_entry **lock_list, *lle; struct lock_instance *instance; struct lock_class *class; - struct proc *p; int i, j; int s; if (witness_cold || lock->lo_witness == NULL || panicstr != NULL || db_active) return; - p = curproc; class = LOCK_CLASS(lock); /* Find lock instance associated with this lock. */ - if (class->lc_flags & LC_SLEEPLOCK) + if (class->lc_flags & LC_SLEEPLOCK) { + struct proc *p; + + p = curproc; + if (p == NULL) + return; lock_list = &p->p_sleeplocks; - else + } else lock_list = &witness_cpu[cpu_number()].wc_spinlocks; s = splhigh(); -- 2.20.1