xref: /freebsd/sys/kern/kern_ucoredump.c (revision d5bc81e6c76ba6fcf4c7a813e3b9731a7889d64e)
1*d5bc81e6SKyle Evans /*
2*d5bc81e6SKyle Evans  * SPDX-License-Identifier: BSD-3-Clause
3*d5bc81e6SKyle Evans  *
4*d5bc81e6SKyle Evans  * Copyright (c) 1982, 1986, 1989, 1991, 1993
5*d5bc81e6SKyle Evans  *	The Regents of the University of California.  All rights reserved.
6*d5bc81e6SKyle Evans  * (c) UNIX System Laboratories, Inc.
7*d5bc81e6SKyle Evans  * All or some portions of this file are derived from material licensed
8*d5bc81e6SKyle Evans  * to the University of California by American Telephone and Telegraph
9*d5bc81e6SKyle Evans  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10*d5bc81e6SKyle Evans  * the permission of UNIX System Laboratories, Inc.
11*d5bc81e6SKyle Evans  *
12*d5bc81e6SKyle Evans  * Redistribution and use in source and binary forms, with or without
13*d5bc81e6SKyle Evans  * modification, are permitted provided that the following conditions
14*d5bc81e6SKyle Evans  * are met:
15*d5bc81e6SKyle Evans  * 1. Redistributions of source code must retain the above copyright
16*d5bc81e6SKyle Evans  *    notice, this list of conditions and the following disclaimer.
17*d5bc81e6SKyle Evans  * 2. Redistributions in binary form must reproduce the above copyright
18*d5bc81e6SKyle Evans  *    notice, this list of conditions and the following disclaimer in the
19*d5bc81e6SKyle Evans  *    documentation and/or other materials provided with the distribution.
20*d5bc81e6SKyle Evans  * 3. Neither the name of the University nor the names of its contributors
21*d5bc81e6SKyle Evans  *    may be used to endorse or promote products derived from this software
22*d5bc81e6SKyle Evans  *    without specific prior written permission.
23*d5bc81e6SKyle Evans  *
24*d5bc81e6SKyle Evans  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25*d5bc81e6SKyle Evans  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26*d5bc81e6SKyle Evans  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27*d5bc81e6SKyle Evans  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28*d5bc81e6SKyle Evans  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29*d5bc81e6SKyle Evans  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30*d5bc81e6SKyle Evans  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31*d5bc81e6SKyle Evans  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32*d5bc81e6SKyle Evans  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33*d5bc81e6SKyle Evans  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34*d5bc81e6SKyle Evans  * SUCH DAMAGE.
35*d5bc81e6SKyle Evans  */
36*d5bc81e6SKyle Evans 
37*d5bc81e6SKyle Evans #include <sys/param.h>
38*d5bc81e6SKyle Evans #include <sys/acct.h>
39*d5bc81e6SKyle Evans #include <sys/compressor.h>
40*d5bc81e6SKyle Evans #include <sys/jail.h>
41*d5bc81e6SKyle Evans #include <sys/lock.h>
42*d5bc81e6SKyle Evans #include <sys/mutex.h>
43*d5bc81e6SKyle Evans #include <sys/proc.h>
44*d5bc81e6SKyle Evans #include <sys/signalvar.h>
45*d5bc81e6SKyle Evans #include <sys/racct.h>
46*d5bc81e6SKyle Evans #include <sys/resourcevar.h>
47*d5bc81e6SKyle Evans #include <sys/sysctl.h>
48*d5bc81e6SKyle Evans #include <sys/syslog.h>
49*d5bc81e6SKyle Evans #include <sys/ucoredump.h>
50*d5bc81e6SKyle Evans #include <sys/wait.h>
51*d5bc81e6SKyle Evans 
52*d5bc81e6SKyle Evans static int coredump(struct thread *td);
53*d5bc81e6SKyle Evans 
54*d5bc81e6SKyle Evans int compress_user_cores = 0;
55*d5bc81e6SKyle Evans 
56*d5bc81e6SKyle Evans static int kern_logsigexit = 1;
57*d5bc81e6SKyle Evans SYSCTL_INT(_kern, KERN_LOGSIGEXIT, logsigexit, CTLFLAG_RW,
58*d5bc81e6SKyle Evans     &kern_logsigexit, 0,
59*d5bc81e6SKyle Evans     "Log processes quitting on abnormal signals to syslog(3)");
60*d5bc81e6SKyle Evans 
61*d5bc81e6SKyle Evans static int sugid_coredump;
62*d5bc81e6SKyle Evans SYSCTL_INT(_kern, OID_AUTO, sugid_coredump, CTLFLAG_RWTUN,
63*d5bc81e6SKyle Evans     &sugid_coredump, 0, "Allow setuid and setgid processes to dump core");
64*d5bc81e6SKyle Evans 
65*d5bc81e6SKyle Evans static int do_coredump = 1;
66*d5bc81e6SKyle Evans SYSCTL_INT(_kern, OID_AUTO, coredump, CTLFLAG_RW,
67*d5bc81e6SKyle Evans 	&do_coredump, 0, "Enable/Disable coredumps");
68*d5bc81e6SKyle Evans 
69*d5bc81e6SKyle Evans static int
70*d5bc81e6SKyle Evans sysctl_compress_user_cores(SYSCTL_HANDLER_ARGS)
71*d5bc81e6SKyle Evans {
72*d5bc81e6SKyle Evans 	int error, val;
73*d5bc81e6SKyle Evans 
74*d5bc81e6SKyle Evans 	val = compress_user_cores;
75*d5bc81e6SKyle Evans 	error = sysctl_handle_int(oidp, &val, 0, req);
76*d5bc81e6SKyle Evans 	if (error != 0 || req->newptr == NULL)
77*d5bc81e6SKyle Evans 		return (error);
78*d5bc81e6SKyle Evans 	if (val != 0 && !compressor_avail(val))
79*d5bc81e6SKyle Evans 		return (EINVAL);
80*d5bc81e6SKyle Evans 	compress_user_cores = val;
81*d5bc81e6SKyle Evans 	return (error);
82*d5bc81e6SKyle Evans }
83*d5bc81e6SKyle Evans SYSCTL_PROC(_kern, OID_AUTO, compress_user_cores,
84*d5bc81e6SKyle Evans     CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 0, sizeof(int),
85*d5bc81e6SKyle Evans     sysctl_compress_user_cores, "I",
86*d5bc81e6SKyle Evans     "Enable compression of user corefiles ("
87*d5bc81e6SKyle Evans     __XSTRING(COMPRESS_GZIP) " = gzip, "
88*d5bc81e6SKyle Evans     __XSTRING(COMPRESS_ZSTD) " = zstd)");
89*d5bc81e6SKyle Evans 
90*d5bc81e6SKyle Evans int compress_user_cores_level = 6;
91*d5bc81e6SKyle Evans SYSCTL_INT(_kern, OID_AUTO, compress_user_cores_level, CTLFLAG_RWTUN,
92*d5bc81e6SKyle Evans     &compress_user_cores_level, 0,
93*d5bc81e6SKyle Evans     "Corefile compression level");
94*d5bc81e6SKyle Evans 
95*d5bc81e6SKyle Evans /*
96*d5bc81e6SKyle Evans  * Force the current process to exit with the specified signal, dumping core
97*d5bc81e6SKyle Evans  * if appropriate.  We bypass the normal tests for masked and caught signals,
98*d5bc81e6SKyle Evans  * allowing unrecoverable failures to terminate the process without changing
99*d5bc81e6SKyle Evans  * signal state.  Mark the accounting record with the signal termination.
100*d5bc81e6SKyle Evans  * If dumping core, save the signal number for the debugger.  Calls exit and
101*d5bc81e6SKyle Evans  * does not return.
102*d5bc81e6SKyle Evans  */
103*d5bc81e6SKyle Evans void
104*d5bc81e6SKyle Evans sigexit(struct thread *td, int sig)
105*d5bc81e6SKyle Evans {
106*d5bc81e6SKyle Evans 	struct proc *p = td->td_proc;
107*d5bc81e6SKyle Evans 	const char *coreinfo;
108*d5bc81e6SKyle Evans 	int rv;
109*d5bc81e6SKyle Evans 	bool logexit;
110*d5bc81e6SKyle Evans 
111*d5bc81e6SKyle Evans 	PROC_LOCK_ASSERT(p, MA_OWNED);
112*d5bc81e6SKyle Evans 	proc_set_p2_wexit(p);
113*d5bc81e6SKyle Evans 
114*d5bc81e6SKyle Evans 	p->p_acflag |= AXSIG;
115*d5bc81e6SKyle Evans 	if ((p->p_flag2 & P2_LOGSIGEXIT_CTL) == 0)
116*d5bc81e6SKyle Evans 		logexit = kern_logsigexit != 0;
117*d5bc81e6SKyle Evans 	else
118*d5bc81e6SKyle Evans 		logexit = (p->p_flag2 & P2_LOGSIGEXIT_ENABLE) != 0;
119*d5bc81e6SKyle Evans 
120*d5bc81e6SKyle Evans 	/*
121*d5bc81e6SKyle Evans 	 * We must be single-threading to generate a core dump.  This
122*d5bc81e6SKyle Evans 	 * ensures that the registers in the core file are up-to-date.
123*d5bc81e6SKyle Evans 	 * Also, the ELF dump handler assumes that the thread list doesn't
124*d5bc81e6SKyle Evans 	 * change out from under it.
125*d5bc81e6SKyle Evans 	 *
126*d5bc81e6SKyle Evans 	 * XXX If another thread attempts to single-thread before us
127*d5bc81e6SKyle Evans 	 *     (e.g. via fork()), we won't get a dump at all.
128*d5bc81e6SKyle Evans 	 */
129*d5bc81e6SKyle Evans 	if (sig_do_core(sig) && thread_single(p, SINGLE_NO_EXIT) == 0) {
130*d5bc81e6SKyle Evans 		p->p_sig = sig;
131*d5bc81e6SKyle Evans 		/*
132*d5bc81e6SKyle Evans 		 * Log signals which would cause core dumps
133*d5bc81e6SKyle Evans 		 * (Log as LOG_INFO to appease those who don't want
134*d5bc81e6SKyle Evans 		 * these messages.)
135*d5bc81e6SKyle Evans 		 * XXX : Todo, as well as euid, write out ruid too
136*d5bc81e6SKyle Evans 		 * Note that coredump() drops proc lock.
137*d5bc81e6SKyle Evans 		 */
138*d5bc81e6SKyle Evans 		rv = coredump(td);
139*d5bc81e6SKyle Evans 		switch (rv) {
140*d5bc81e6SKyle Evans 		case 0:
141*d5bc81e6SKyle Evans 			sig |= WCOREFLAG;
142*d5bc81e6SKyle Evans 			coreinfo = " (core dumped)";
143*d5bc81e6SKyle Evans 			break;
144*d5bc81e6SKyle Evans 		case EFAULT:
145*d5bc81e6SKyle Evans 			coreinfo = " (no core dump - bad address)";
146*d5bc81e6SKyle Evans 			break;
147*d5bc81e6SKyle Evans 		case EINVAL:
148*d5bc81e6SKyle Evans 			coreinfo = " (no core dump - invalid argument)";
149*d5bc81e6SKyle Evans 			break;
150*d5bc81e6SKyle Evans 		case EFBIG:
151*d5bc81e6SKyle Evans 			coreinfo = " (no core dump - too large)";
152*d5bc81e6SKyle Evans 			break;
153*d5bc81e6SKyle Evans 		default:
154*d5bc81e6SKyle Evans 			coreinfo = " (no core dump - other error)";
155*d5bc81e6SKyle Evans 			break;
156*d5bc81e6SKyle Evans 		}
157*d5bc81e6SKyle Evans 		if (logexit)
158*d5bc81e6SKyle Evans 			log(LOG_INFO,
159*d5bc81e6SKyle Evans 			    "pid %d (%s), jid %d, uid %d: exited on "
160*d5bc81e6SKyle Evans 			    "signal %d%s\n", p->p_pid, p->p_comm,
161*d5bc81e6SKyle Evans 			    p->p_ucred->cr_prison->pr_id,
162*d5bc81e6SKyle Evans 			    td->td_ucred->cr_uid,
163*d5bc81e6SKyle Evans 			    sig &~ WCOREFLAG, coreinfo);
164*d5bc81e6SKyle Evans 	} else
165*d5bc81e6SKyle Evans 		PROC_UNLOCK(p);
166*d5bc81e6SKyle Evans 	exit1(td, 0, sig);
167*d5bc81e6SKyle Evans 	/* NOTREACHED */
168*d5bc81e6SKyle Evans }
169*d5bc81e6SKyle Evans 
170*d5bc81e6SKyle Evans 
171*d5bc81e6SKyle Evans /*
172*d5bc81e6SKyle Evans  * Dump a process' core.  The main routine does some
173*d5bc81e6SKyle Evans  * policy checking, and creates the name of the coredump;
174*d5bc81e6SKyle Evans  * then it passes on a vnode and a size limit to the process-specific
175*d5bc81e6SKyle Evans  * coredump routine if there is one; if there _is not_ one, it returns
176*d5bc81e6SKyle Evans  * ENOSYS; otherwise it returns the error from the process-specific routine.
177*d5bc81e6SKyle Evans  */
178*d5bc81e6SKyle Evans static int
179*d5bc81e6SKyle Evans coredump(struct thread *td)
180*d5bc81e6SKyle Evans {
181*d5bc81e6SKyle Evans 	struct proc *p = td->td_proc;
182*d5bc81e6SKyle Evans 	off_t limit;
183*d5bc81e6SKyle Evans 	int error;
184*d5bc81e6SKyle Evans 
185*d5bc81e6SKyle Evans 	PROC_LOCK_ASSERT(p, MA_OWNED);
186*d5bc81e6SKyle Evans 	MPASS((p->p_flag & P_HADTHREADS) == 0 || p->p_singlethread == td);
187*d5bc81e6SKyle Evans 
188*d5bc81e6SKyle Evans 	if (!do_coredump || (!sugid_coredump && (p->p_flag & P_SUGID) != 0) ||
189*d5bc81e6SKyle Evans 	    (p->p_flag2 & P2_NOTRACE) != 0) {
190*d5bc81e6SKyle Evans 		PROC_UNLOCK(p);
191*d5bc81e6SKyle Evans 		return (EFAULT);
192*d5bc81e6SKyle Evans 	}
193*d5bc81e6SKyle Evans 
194*d5bc81e6SKyle Evans 	/*
195*d5bc81e6SKyle Evans 	 * Note that the bulk of limit checking is done after
196*d5bc81e6SKyle Evans 	 * the corefile is created.  The exception is if the limit
197*d5bc81e6SKyle Evans 	 * for corefiles is 0, in which case we don't bother
198*d5bc81e6SKyle Evans 	 * creating the corefile at all.  This layout means that
199*d5bc81e6SKyle Evans 	 * a corefile is truncated instead of not being created,
200*d5bc81e6SKyle Evans 	 * if it is larger than the limit.
201*d5bc81e6SKyle Evans 	 */
202*d5bc81e6SKyle Evans 	limit = (off_t)lim_cur(td, RLIMIT_CORE);
203*d5bc81e6SKyle Evans 	if (limit == 0 || racct_get_available(p, RACCT_CORE) == 0) {
204*d5bc81e6SKyle Evans 		PROC_UNLOCK(p);
205*d5bc81e6SKyle Evans 		return (EFBIG);
206*d5bc81e6SKyle Evans 	}
207*d5bc81e6SKyle Evans 
208*d5bc81e6SKyle Evans 	error = coredump_vnode(td, limit);
209*d5bc81e6SKyle Evans 	PROC_LOCK_ASSERT(p, MA_NOTOWNED);
210*d5bc81e6SKyle Evans 
211*d5bc81e6SKyle Evans 	return (error);
212*d5bc81e6SKyle Evans }
213