From 22ea1bc57a98ebb5e159f38635e3a3c2423c716f Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Thu, 27 Jul 2006 22:32:30 +0000 Subject: Unify the checking for lock misbehavior in the various syscall() implementations and adjust some of the checks while I'm here: - Add a new check to make sure we don't return from a syscall in a critical section. - Add a new explicit check before userret() to make sure we don't return with any locks held. The advantage here is that we can include the syscall number and name in syscall() whereas that info is not available in userret(). - Drop the mtx_assert()'s of sched_lock and Giant. They are replaced by the more general checks just added. MFC after: 2 weeks --- sys/amd64/amd64/trap.c | 20 +++++++++++++------- sys/amd64/ia32/ia32_syscall.c | 18 +++++++++++++----- sys/arm/arm/trap.c | 16 ++++++++++++---- sys/conf/files | 2 +- sys/i386/i386/trap.c | 20 +++++++++++++------- sys/ia64/ia32/ia32_trap.c | 20 +++++++++++++------- sys/ia64/ia64/trap.c | 20 +++++++++++++------- sys/powerpc/aim/trap.c | 18 +++++++++++++----- sys/powerpc/powerpc/trap.c | 18 +++++++++++++----- sys/sparc64/sparc64/trap.c | 18 +++++++++++++----- 10 files changed, 117 insertions(+), 53 deletions(-) (limited to 'sys') diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index d41318cd4c6d..415d695c2842 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -145,9 +145,7 @@ static int panic_on_nmi = 1; SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RW, &panic_on_nmi, 0, "Panic on NMI"); -#ifdef WITNESS extern char *syscallnames[]; -#endif /* * Exception, fault, and trap interface to the FreeBSD kernel. @@ -873,6 +871,19 @@ syscall(frame) trapsignal(td, &ksi); } + /* + * Check for misbehavior. + */ + WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"); + KASSERT(td->td_critnest == 0, + ("System call %s returning in a critical section", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???")); + KASSERT(td->td_locks == 0, + ("System call %s returning with %d locks held", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???", + td->td_locks)); + /* * Handle reschedule and other end-of-syscall issues */ @@ -894,9 +905,4 @@ syscall(frame) STOPEVENT(p, S_SCX, code); PTRACESTOP_SC(p, td, S_PT_SCX); - - WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", - (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"); - mtx_assert(&sched_lock, MA_NOTOWNED); - mtx_assert(&Giant, MA_NOTOWNED); } diff --git a/sys/amd64/ia32/ia32_syscall.c b/sys/amd64/ia32/ia32_syscall.c index 5b3086a9d4f5..644235dc3bf9 100644 --- a/sys/amd64/ia32/ia32_syscall.c +++ b/sys/amd64/ia32/ia32_syscall.c @@ -243,6 +243,19 @@ ia32_syscall(struct trapframe frame) trapsignal(td, &ksi); } + /* + * Check for misbehavior. + */ + WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", + (code >= 0 && code < SYS_MAXSYSCALL) ? freebsd32_syscallnames[code] : "???"); + KASSERT(td->td_critnest == 0, + ("System call %s returning in a critical section", + (code >= 0 && code < SYS_MAXSYSCALL) ? freebsd32_syscallnames[code] : "???")); + KASSERT(td->td_locks == 0, + ("System call %s returning with %d locks held", + (code >= 0 && code < SYS_MAXSYSCALL) ? freebsd32_syscallnames[code] : "???", + td->td_locks)); + /* * Handle reschedule and other end-of-syscall issues */ @@ -263,11 +276,6 @@ ia32_syscall(struct trapframe frame) STOPEVENT(p, S_SCX, code); PTRACESTOP_SC(p, td, S_PT_SCX); - - WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", - (code >= 0 && code < SYS_MAXSYSCALL) ? freebsd32_syscallnames[code] : "???"); - mtx_assert(&sched_lock, MA_NOTOWNED); - mtx_assert(&Giant, MA_NOTOWNED); } diff --git a/sys/arm/arm/trap.c b/sys/arm/arm/trap.c index b1534fe5d092..1cb53dbcc3c8 100644 --- a/sys/arm/arm/trap.c +++ b/sys/arm/arm/trap.c @@ -133,6 +133,7 @@ void undefinedinstruction(trapframe_t *); #include extern char fusubailout[]; +extern char *syscallnames[]; #ifdef DEBUG int last_fault_code; /* For the benefit of pmap_fault_fixup() */ @@ -979,8 +980,17 @@ bad: } if (locked && (callp->sy_narg & SYF_MPSAFE) == 0) mtx_unlock(&Giant); - - + + WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"); + KASSERT(td->td_critnest == 0, + ("System call %s returning in a critical section", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???")); + KASSERT(td->td_locks == 0, + ("System call %s returning with %d locks held", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???", + td->td_locks)); + userret(td, frame); CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td, td->td_proc->p_pid, td->td_proc->p_comm, code); @@ -991,8 +1001,6 @@ bad: if (KTRPOINT(td, KTR_SYSRET)) ktrsysret(code, error, td->td_retval[0]); #endif - mtx_assert(&sched_lock, MA_NOTOWNED); - mtx_assert(&Giant, MA_NOTOWNED); } void diff --git a/sys/conf/files b/sys/conf/files index 24c8cf5b5cec..a02023bc480d 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1402,7 +1402,7 @@ kern/sys_generic.c standard kern/sys_pipe.c standard kern/sys_process.c standard kern/sys_socket.c standard -kern/syscalls.c optional witness +kern/syscalls.c optional witness | invariants kern/sysv_ipc.c standard kern/sysv_msg.c optional sysvmsg kern/sysv_sem.c optional sysvsem diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c index cce7038a2543..da3ed95f4152 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -159,9 +159,7 @@ static int panic_on_nmi = 1; SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RW, &panic_on_nmi, 0, "Panic on NMI"); -#ifdef WITNESS extern char *syscallnames[]; -#endif /* * Exception, fault, and trap interface to the FreeBSD kernel. @@ -1064,6 +1062,19 @@ syscall(frame) trapsignal(td, &ksi); } + /* + * Check for misbehavior. + */ + WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"); + KASSERT(td->td_critnest == 0, + ("System call %s returning in a critical section", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???")); + KASSERT(td->td_locks == 0, + ("System call %s returning with %d locks held", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???", + td->td_locks)); + /* * Handle reschedule and other end-of-syscall issues */ @@ -1085,10 +1096,5 @@ syscall(frame) STOPEVENT(p, S_SCX, code); PTRACESTOP_SC(p, td, S_PT_SCX); - - WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", - (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"); - mtx_assert(&sched_lock, MA_NOTOWNED); - mtx_assert(&Giant, MA_NOTOWNED); } diff --git a/sys/ia64/ia32/ia32_trap.c b/sys/ia64/ia32/ia32_trap.c index c3cacf5c6b65..f63ae941b6fe 100644 --- a/sys/ia64/ia32/ia32_trap.c +++ b/sys/ia64/ia32/ia32_trap.c @@ -46,9 +46,7 @@ __FBSDID("$FreeBSD$"); #include #include -#ifdef WITNESS extern char *syscallnames[]; -#endif static void ia32_syscall(struct trapframe *tf) @@ -182,6 +180,19 @@ ia32_syscall(struct trapframe *tf) trapsignal(td, &ksi); } + /* + * Check for misbehavior. + */ + WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"); + KASSERT(td->td_critnest == 0, + ("System call %s returning in a critical section", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???")); + KASSERT(td->td_locks == 0, + ("System call %s returning with %d locks held", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???", + td->td_locks)); + /* * End of syscall tracing. */ @@ -200,11 +211,6 @@ ia32_syscall(struct trapframe *tf) STOPEVENT(p, S_SCX, code); PTRACESTOP_SC(p, td, S_PT_SCX); - - WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", - (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"); - mtx_assert(&sched_lock, MA_NOTOWNED); - mtx_assert(&Giant, MA_NOTOWNED); } /* diff --git a/sys/ia64/ia64/trap.c b/sys/ia64/ia64/trap.c index 93b518d2790e..d0f3c9846614 100644 --- a/sys/ia64/ia64/trap.c +++ b/sys/ia64/ia64/trap.c @@ -85,9 +85,7 @@ static void break_syscall(struct trapframe *tf); */ extern struct fpswa_iface *fpswa_iface; -#ifdef WITNESS extern char *syscallnames[]; -#endif static const char *ia64_vector_names[] = { "VHPT Translation", /* 0 */ @@ -1048,6 +1046,19 @@ syscall(struct trapframe *tf) } } + /* + * Check for misbehavior. + */ + WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"); + KASSERT(td->td_critnest == 0, + ("System call %s returning in a critical section", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???")); + KASSERT(td->td_locks == 0, + ("System call %s returning with %d locks held", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???", + td->td_locks)); + /* * Handle reschedule and other end-of-syscall issues */ @@ -1069,10 +1080,5 @@ syscall(struct trapframe *tf) PTRACESTOP_SC(p, td, S_PT_SCX); - WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", - (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"); - mtx_assert(&sched_lock, MA_NOTOWNED); - mtx_assert(&Giant, MA_NOTOWNED); - return (error); } diff --git a/sys/powerpc/aim/trap.c b/sys/powerpc/aim/trap.c index 527e9fb93b57..0f5961bbb269 100644 --- a/sys/powerpc/aim/trap.c +++ b/sys/powerpc/aim/trap.c @@ -470,6 +470,19 @@ syscall(struct trapframe *frame) if ((callp->sy_narg & SYF_MPSAFE) == 0) mtx_unlock(&Giant); + /* + * Check for misbehavior. + */ + WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"); + KASSERT(td->td_critnest == 0, + ("System call %s returning in a critical section", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???")); + KASSERT(td->td_locks == 0, + ("System call %s returning with %d locks held", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???", + td->td_locks)); + #ifdef KTRACE if (KTRPOINT(td, KTR_SYSRET)) ktrsysret(code, error, td->td_retval[0]); @@ -481,11 +494,6 @@ syscall(struct trapframe *frame) STOPEVENT(p, S_SCX, code); PTRACESTOP_SC(p, td, S_PT_SCX); - - WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", - (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"); - mtx_assert(&sched_lock, MA_NOTOWNED); - mtx_assert(&Giant, MA_NOTOWNED); } static int diff --git a/sys/powerpc/powerpc/trap.c b/sys/powerpc/powerpc/trap.c index 527e9fb93b57..0f5961bbb269 100644 --- a/sys/powerpc/powerpc/trap.c +++ b/sys/powerpc/powerpc/trap.c @@ -470,6 +470,19 @@ syscall(struct trapframe *frame) if ((callp->sy_narg & SYF_MPSAFE) == 0) mtx_unlock(&Giant); + /* + * Check for misbehavior. + */ + WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"); + KASSERT(td->td_critnest == 0, + ("System call %s returning in a critical section", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???")); + KASSERT(td->td_locks == 0, + ("System call %s returning with %d locks held", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???", + td->td_locks)); + #ifdef KTRACE if (KTRPOINT(td, KTR_SYSRET)) ktrsysret(code, error, td->td_retval[0]); @@ -481,11 +494,6 @@ syscall(struct trapframe *frame) STOPEVENT(p, S_SCX, code); PTRACESTOP_SC(p, td, S_PT_SCX); - - WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", - (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"); - mtx_assert(&sched_lock, MA_NOTOWNED); - mtx_assert(&Giant, MA_NOTOWNED); } static int diff --git a/sys/sparc64/sparc64/trap.c b/sys/sparc64/sparc64/trap.c index f45d273f532e..b1c0dcc202ee 100644 --- a/sys/sparc64/sparc64/trap.c +++ b/sys/sparc64/sparc64/trap.c @@ -647,6 +647,19 @@ syscall(struct trapframe *tf) if ((callp->sy_narg & SYF_MPSAFE) == 0) mtx_unlock(&Giant); + /* + * Check for misbehavior. + */ + WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"); + KASSERT(td->td_critnest == 0, + ("System call %s returning in a critical section", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???")); + KASSERT(td->td_locks == 0, + ("System call %s returning with %d locks held", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???", + td->td_locks)); + /* * Handle reschedule and other end-of-syscall issues */ @@ -664,9 +677,4 @@ syscall(struct trapframe *tf) STOPEVENT(p, S_SCX, code); PTRACESTOP_SC(p, td, S_PT_SCX); - - WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", - (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"); - mtx_assert(&sched_lock, MA_NOTOWNED); - mtx_assert(&Giant, MA_NOTOWNED); } -- cgit v1.3