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 @@ -52,9 +52,21 @@ .Xr savecore 8 . ) .Pp The maximum size of a core file is limited by -.Xr setrlimit 2 . +.Xr setrlimit 2 limit +.Dv RLIMIT_CORE . Files which would be larger than the limit are not created. .Pp +With the limit large enough, processes that mapped a very large, +and perhaps sparcely populated, virtual memory regions, could take +a very long time to create core dumps. +Signals cannot interrupt the write of the core dump, except +.Dv SIGKILL . +The later behavior can be disabled by setting +.Xr sysctl 8 +variable +.Va kern.core_dump_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_intr = 1; +SYSCTL_INT(_kern, OID_AUTO, core_dump_intr, CTLFLAG_RW, + &core_dump_intr, 0, + "Core dumping interruptible with SIGKILL"); + static int sysctl_kern_ps_strings(SYSCTL_HANDLER_ARGS) { @@ -1926,7 +1931,7 @@ struct mount *mp; size_t resid, runlen; int error; - bool success; + bool interrupted, success; KASSERT((uintptr_t)base % PAGE_SIZE == 0, ("%s: user address %p is not page-aligned", __func__, base)); @@ -1935,7 +1940,8 @@ return (compress_chunk(cp, base, tmpbuf, len)); map = &cp->td->td_proc->p_vmspace->vm_map; - for (; len > 0; base += runlen, offset += runlen, len -= runlen) { + for (interrupted = false; len > 0; + base += runlen, offset += runlen, len -= runlen) { /* * Attempt to page in all virtual pages in the range. If a * virtual page is not backed by the pager, it is represented as @@ -1943,6 +1949,12 @@ * anonymous memory or truncated files, for example. */ for (runlen = 0; runlen < len; runlen += PAGE_SIZE) { + if (core_dump_intr && curproc_is_killed_9()) { + error = EINTR; + success = false; + interrupted = true; + break; + } error = vm_fault(map, (uintptr_t)base + runlen, VM_PROT_READ, VM_FAULT_NOFILL, NULL); if (runlen == 0) @@ -1951,6 +1963,8 @@ break; } + if (interrupted) + break; if (success) { error = core_write(cp, base, runlen, offset, UIO_USERSPACE, &resid); 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, @@ -3277,6 +3276,29 @@ return (ret); } +bool +curproc_is_killed_9(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 @@ -1162,7 +1162,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_is_killed_9(void); void userret(struct thread *, struct trapframe *); void cpu_exit(struct thread *);