diff --git a/share/man/man5/core.5 b/share/man/man5/core.5 --- a/share/man/man5/core.5 +++ b/share/man/man5/core.5 @@ -28,7 +28,7 @@ .\" @(#)core.5 8.3 (Berkeley) 12/11/93 .\" $FreeBSD$ .\" -.Dd August 2, 2020 +.Dd October 5, 2021 .Dt CORE 5 .Os .Sh NAME @@ -51,10 +51,26 @@ (In this event, the decision to save the core file is arbitrary, see .Xr savecore 8 . ) .Pp -The maximum size of a core file is limited by -.Xr setrlimit 2 . +The maximum size of a core file is limited by the +.Dv RLIMIT_CORE +.Xr setrlimit 2 +limit. Files which would be larger than the limit are not created. .Pp +With a large limit, a process that had mapped a very large, +and perhaps sparsely populated, virtual memory region, could take +a very long time to create core dumps. +The system ignores all signals sent to a process writing a core file, except +.Dv SIGKILL +which terminates the writing and causes immediate exit of the process. +The behavior of +.Dv SIGKILL +can be disabled by setting tunable +.Xr sysctl 8 +variable +.Va kern.core_dump_can_intr +to zero. +.Pp The name of the file is controlled via the .Xr sysctl 8 variable diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -151,6 +151,11 @@ SYSCTL_INT(_security_bsd, OID_AUTO, map_at_zero, CTLFLAG_RWTUN, &map_at_zero, 0, "Permit processes to map an object at virtual address 0."); +static int core_dump_can_intr = 1; +SYSCTL_INT(_kern, OID_AUTO, core_dump_can_intr, CTLFLAG_RWTUN, + &core_dump_can_intr, 0, + "Core dumping interruptible with SIGKILL"); + static int sysctl_kern_ps_strings(SYSCTL_HANDLER_ARGS) { @@ -1943,6 +1948,8 @@ * anonymous memory or truncated files, for example. */ for (runlen = 0; runlen < len; runlen += PAGE_SIZE) { + if (core_dump_can_intr && curproc_sigkilled()) + return (EINTR); error = vm_fault(map, (uintptr_t)base + runlen, VM_PROT_READ, VM_FAULT_NOFILL, NULL); if (runlen == 0) diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -214,7 +214,6 @@ #define SIGPROP_TTYSTOP 0x08 /* ditto, from tty */ #define SIGPROP_IGNORE 0x10 /* ignore by default */ #define SIGPROP_CONT 0x20 /* continue if suspended */ -#define SIGPROP_CANTMASK 0x40 /* non-maskable, catchable */ static int sigproptbl[NSIG] = { [SIGHUP] = SIGPROP_KILL, @@ -3297,6 +3296,29 @@ return (ret); } +bool +curproc_sigkilled(void) +{ + struct thread *td; + struct proc *p; + struct sigacts *ps; + bool res; + + td = curthread; + if ((td->td_flags & TDF_NEEDSIGCHK) == 0) + return (false); + + p = td->td_proc; + PROC_LOCK(p); + ps = p->p_sigacts; + mtx_lock(&ps->ps_mtx); + res = SIGISMEMBER(td->td_sigqueue.sq_signals, SIGKILL) || + SIGISMEMBER(p->p_sigqueue.sq_signals, SIGKILL); + mtx_unlock(&ps->ps_mtx); + PROC_UNLOCK(p); + return (res); +} + void proc_wkilled(struct proc *p) { diff --git a/sys/sys/proc.h b/sys/sys/proc.h --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -1161,7 +1161,7 @@ extern void (*cpu_idle_hook)(sbintime_t); /* Hook to machdep CPU idler. */ void cpu_switch(struct thread *, struct thread *, struct mtx *); void cpu_throw(struct thread *, struct thread *) __dead2; -void unsleep(struct thread *); +bool curproc_sigkilled(void); void userret(struct thread *, struct trapframe *); void cpu_exit(struct thread *);