summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authordas <das@FreeBSD.org>2005-04-10 02:31:24 +0000
committerdas <das@FreeBSD.org>2005-04-10 02:31:24 +0000
commit7a8e8974c6883f1271b991a821221694cdddabdd (patch)
tree165ccabd054b6478825428998a06587d4d4a4118 /sys/kern
parentc5df80448a267ce23fd68d7f4fcb3025bc18eb51 (diff)
downloadFreeBSD-src-7a8e8974c6883f1271b991a821221694cdddabdd.zip
FreeBSD-src-7a8e8974c6883f1271b991a821221694cdddabdd.tar.gz
Suspend all other threads in the process while generating a core dump.
The main reason for doing this is that the ELF dump handler expects the thread list to be fixed while the dump header is generated, so an upcall that occurs at the wrong time can lead to buffer overruns and other Bad Things. Another solution would be to grab sched_lock in the ELF dump handler, but we might as well single-thread, since the process is about to die. Furthermore, I think this should ensure that the register sets in the core file are sequentially consistent.
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_sig.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 7928120..71427d7 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -2430,7 +2430,16 @@ sigexit(td, sig)
PROC_LOCK_ASSERT(p, MA_OWNED);
p->p_acflag |= AXSIG;
- if (sigprop(sig) & SA_CORE) {
+ /*
+ * We must be single-threading to generate a core dump. This
+ * ensures that the registers in the core file are up-to-date.
+ * Also, the ELF dump handler assumes that the thread list doesn't
+ * change out from under it.
+ *
+ * XXX If another thread attempts to single-thread before us
+ * (e.g. via fork()), we won't get a dump at all.
+ */
+ if ((sigprop(sig) & SA_CORE) && (thread_single(SINGLE_NO_EXIT) == 0)) {
p->p_sig = sig;
/*
* Log signals which would cause core dumps
@@ -2553,6 +2562,7 @@ coredump(struct thread *td)
off_t limit;
PROC_LOCK_ASSERT(p, MA_OWNED);
+ MPASS((p->p_flag & P_HADTHREADS) == 0 || p->p_singlethread == td);
_STOPEVENT(p, S_CORE, 0);
if (((sugid_coredump == 0) && p->p_flag & P_SUGID) || do_coredump == 0) {
OpenPOWER on IntegriCloud