mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
- Add code to detect if a system call returns with locks other than Giant
held and panic if so (conditional on witness). - Change witness_list to return the number of locks held so this is easier. - Add kern/syscalls.c to the kernel build if witness is defined so that the panic message can contain the name of the offending system call. - Add assertions that Giant and sched_lock are not held when returning from a system call, which were missing for alpha and ia64.
This commit is contained in:
parent
d664747bfa
commit
92cf772d8d
10 changed files with 78 additions and 4 deletions
|
|
@ -88,6 +88,11 @@ int unaligned_fixup __P((unsigned long, unsigned long,
|
|||
|
||||
static void printtrap __P((const unsigned long, const unsigned long,
|
||||
const unsigned long, const unsigned long, struct trapframe *, int, int));
|
||||
|
||||
#ifdef WITNESS
|
||||
extern char *syscallnames[];
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define the code needed before returning to user mode, for
|
||||
* trap and syscall.
|
||||
|
|
@ -737,6 +742,15 @@ syscall(code, framep)
|
|||
*/
|
||||
STOPEVENT(p, S_SCX, code);
|
||||
mtx_exit(&Giant, MTX_DEF);
|
||||
|
||||
mtx_assert(&sched_lock, MA_NOTOWNED);
|
||||
mtx_assert(&Giant, MA_NOTOWNED);
|
||||
#ifdef WITNESS
|
||||
if (witness_list(p)) {
|
||||
panic("system call %s returning with mutex(s) held\n",
|
||||
syscallnames[code]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -164,6 +164,10 @@ 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
|
||||
|
||||
static __inline int
|
||||
userret(p, frame, oticks, have_giant)
|
||||
struct proc *p;
|
||||
|
|
@ -1221,6 +1225,12 @@ bad:
|
|||
|
||||
mtx_assert(&sched_lock, MA_NOTOWNED);
|
||||
mtx_assert(&Giant, MA_NOTOWNED);
|
||||
#ifdef WITNESS
|
||||
if (witness_list(p)) {
|
||||
panic("system call %s returning with mutex(s) held\n",
|
||||
syscallnames[code]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -664,6 +664,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/sysv_ipc.c standard
|
||||
kern/sysv_msg.c optional sysvmsg
|
||||
kern/sysv_sem.c optional sysvsem
|
||||
|
|
|
|||
|
|
@ -164,6 +164,10 @@ 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
|
||||
|
||||
static __inline int
|
||||
userret(p, frame, oticks, have_giant)
|
||||
struct proc *p;
|
||||
|
|
@ -1221,6 +1225,12 @@ bad:
|
|||
|
||||
mtx_assert(&sched_lock, MA_NOTOWNED);
|
||||
mtx_assert(&Giant, MA_NOTOWNED);
|
||||
#ifdef WITNESS
|
||||
if (witness_list(p)) {
|
||||
panic("system call %s returning with mutex(s) held\n",
|
||||
syscallnames[code]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -74,6 +74,10 @@ u_int32_t want_resched;
|
|||
|
||||
static int unaligned_fixup(struct trapframe *framep, struct proc *p);
|
||||
|
||||
#ifdef WITNESS
|
||||
extern char *syscallnames[];
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define the code needed before returning to user mode, for
|
||||
* trap and syscall.
|
||||
|
|
@ -614,6 +618,16 @@ syscall(int code, u_int64_t *args, struct trapframe *framep)
|
|||
*/
|
||||
STOPEVENT(p, S_SCX, code);
|
||||
mtx_exit(&Giant, MTX_DEF);
|
||||
|
||||
mtx_assert(&sched_lock, MA_NOTOWNED);
|
||||
mtx_assert(&Giant, MA_NOTOWNED);
|
||||
#ifdef WITNESS
|
||||
if (witness_list(p)) {
|
||||
panic("system call %s returning with mutex(s) held\n",
|
||||
syscallnames[code]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1353,17 +1353,22 @@ witness_free(struct witness *w)
|
|||
w_free = w;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
witness_list(struct proc *p)
|
||||
{
|
||||
struct mtx *m;
|
||||
int nheld;
|
||||
|
||||
nheld = 0;
|
||||
for ((m = LIST_FIRST(&p->p_heldmtx)); m != NULL;
|
||||
m = LIST_NEXT(m, mtx_held)) {
|
||||
printf("\t\"%s\" (%p) locked at %s:%d\n",
|
||||
m->mtx_description, m,
|
||||
m->mtx_witness->w_file, m->mtx_witness->w_line);
|
||||
nheld++;
|
||||
}
|
||||
|
||||
return (nheld);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -164,6 +164,10 @@ 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
|
||||
|
||||
static __inline int
|
||||
userret(p, frame, oticks, have_giant)
|
||||
struct proc *p;
|
||||
|
|
@ -1221,6 +1225,12 @@ bad:
|
|||
|
||||
mtx_assert(&sched_lock, MA_NOTOWNED);
|
||||
mtx_assert(&Giant, MA_NOTOWNED);
|
||||
#ifdef WITNESS
|
||||
if (witness_list(p)) {
|
||||
panic("system call %s returning with mutex(s) held\n",
|
||||
syscallnames[code]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -1353,17 +1353,22 @@ witness_free(struct witness *w)
|
|||
w_free = w;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
witness_list(struct proc *p)
|
||||
{
|
||||
struct mtx *m;
|
||||
int nheld;
|
||||
|
||||
nheld = 0;
|
||||
for ((m = LIST_FIRST(&p->p_heldmtx)); m != NULL;
|
||||
m = LIST_NEXT(m, mtx_held)) {
|
||||
printf("\t\"%s\" (%p) locked at %s:%d\n",
|
||||
m->mtx_description, m,
|
||||
m->mtx_witness->w_file, m->mtx_witness->w_line);
|
||||
nheld++;
|
||||
}
|
||||
|
||||
return (nheld);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -1353,17 +1353,22 @@ witness_free(struct witness *w)
|
|||
w_free = w;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
witness_list(struct proc *p)
|
||||
{
|
||||
struct mtx *m;
|
||||
int nheld;
|
||||
|
||||
nheld = 0;
|
||||
for ((m = LIST_FIRST(&p->p_heldmtx)); m != NULL;
|
||||
m = LIST_NEXT(m, mtx_held)) {
|
||||
printf("\t\"%s\" (%p) locked at %s:%d\n",
|
||||
m->mtx_description, m,
|
||||
m->mtx_witness->w_file, m->mtx_witness->w_line);
|
||||
nheld++;
|
||||
}
|
||||
|
||||
return (nheld);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -300,7 +300,7 @@ void witness_enter(struct mtx *, int, const char *, int);
|
|||
void witness_try_enter(struct mtx *, int, const char *, int);
|
||||
void witness_exit(struct mtx *, int, const char *, int);
|
||||
void witness_display(void(*)(const char *fmt, ...));
|
||||
void witness_list(struct proc *);
|
||||
int witness_list(struct proc *);
|
||||
int witness_sleep(int, struct mtx *, const char *, int);
|
||||
void witness_save(struct mtx *, const char **, int *);
|
||||
void witness_restore(struct mtx *, const char *, int);
|
||||
|
|
|
|||
Loading…
Reference in a new issue