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
This commit is contained in:
+13
-7
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+12
-4
@@ -133,6 +133,7 @@ void undefinedinstruction(trapframe_t *);
|
||||
#include <machine/machdep.h>
|
||||
|
||||
extern char fusubailout[];
|
||||
extern char *syscallnames[];
|
||||
|
||||
#ifdef DEBUG
|
||||
int last_fault_code; /* For the benefit of pmap_fault_fixup() */
|
||||
@@ -979,8 +980,17 @@ syscall(struct thread *td, trapframe_t *frame, u_int32_t insn)
|
||||
}
|
||||
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 @@ syscall(struct thread *td, trapframe_t *frame, u_int32_t insn)
|
||||
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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+13
-7
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,9 +46,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/md_var.h>
|
||||
#include <i386/include/psl.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+13
-7
@@ -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);
|
||||
}
|
||||
|
||||
+13
-5
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user