1 /*
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1982, 1986, 1989, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37 #include <sys/param.h>
38 #include <sys/acct.h>
39 #include <sys/compressor.h>
40 #include <sys/jail.h>
41 #include <sys/kernel.h>
42 #include <sys/lock.h>
43 #include <sys/mutex.h>
44 #include <sys/proc.h>
45 #include <sys/signalvar.h>
46 #include <sys/racct.h>
47 #include <sys/resourcevar.h>
48 #include <sys/rmlock.h>
49 #include <sys/sysctl.h>
50 #include <sys/syslog.h>
51 #include <sys/ucoredump.h>
52 #include <sys/wait.h>
53
54 static int coredump(struct thread *td, const char **);
55
56 int compress_user_cores = 0;
57
58 static SLIST_HEAD(, coredumper) coredumpers =
59 SLIST_HEAD_INITIALIZER(coredumpers);
60 static struct rmlock coredump_rmlock;
61 RM_SYSINIT(coredump_lock, &coredump_rmlock, "coredump_lock");
62
63 static int kern_logsigexit = 1;
64 SYSCTL_INT(_kern, KERN_LOGSIGEXIT, logsigexit, CTLFLAG_RW,
65 &kern_logsigexit, 0,
66 "Log processes quitting on abnormal signals to syslog(3)");
67
68 static int sugid_coredump;
69 SYSCTL_INT(_kern, OID_AUTO, sugid_coredump, CTLFLAG_RWTUN,
70 &sugid_coredump, 0, "Allow setuid and setgid processes to dump core");
71
72 static int do_coredump = 1;
73 SYSCTL_INT(_kern, OID_AUTO, coredump, CTLFLAG_RW,
74 &do_coredump, 0, "Enable/Disable coredumps");
75
76 static int
sysctl_compress_user_cores(SYSCTL_HANDLER_ARGS)77 sysctl_compress_user_cores(SYSCTL_HANDLER_ARGS)
78 {
79 int error, val;
80
81 val = compress_user_cores;
82 error = sysctl_handle_int(oidp, &val, 0, req);
83 if (error != 0 || req->newptr == NULL)
84 return (error);
85 if (val != 0 && !compressor_avail(val))
86 return (EINVAL);
87 compress_user_cores = val;
88 return (error);
89 }
90 SYSCTL_PROC(_kern, OID_AUTO, compress_user_cores,
91 CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 0, sizeof(int),
92 sysctl_compress_user_cores, "I",
93 "Enable compression of user corefiles ("
94 __XSTRING(COMPRESS_GZIP) " = gzip, "
95 __XSTRING(COMPRESS_ZSTD) " = zstd)");
96
97 int compress_user_cores_level = 6;
98 SYSCTL_INT(_kern, OID_AUTO, compress_user_cores_level, CTLFLAG_RWTUN,
99 &compress_user_cores_level, 0,
100 "Corefile compression level");
101
102 void
coredumper_register(struct coredumper * cd)103 coredumper_register(struct coredumper *cd)
104 {
105
106 blockcount_init(&cd->cd_refcount);
107 rm_wlock(&coredump_rmlock);
108 SLIST_INSERT_HEAD(&coredumpers, cd, cd_entry);
109 rm_wunlock(&coredump_rmlock);
110 }
111
112 void
coredumper_unregister(struct coredumper * cd)113 coredumper_unregister(struct coredumper *cd)
114 {
115
116 rm_wlock(&coredump_rmlock);
117 SLIST_REMOVE(&coredumpers, cd, coredumper, cd_entry);
118 rm_wunlock(&coredump_rmlock);
119
120 /*
121 * Wait for any in-process coredumps to finish before returning.
122 */
123 blockcount_wait(&cd->cd_refcount, NULL, "dumpwait", 0);
124 }
125
126 /*
127 * Force the current process to exit with the specified signal, dumping core
128 * if appropriate. We bypass the normal tests for masked and caught signals,
129 * allowing unrecoverable failures to terminate the process without changing
130 * signal state. Mark the accounting record with the signal termination.
131 * If dumping core, save the signal number for the debugger. Calls exit and
132 * does not return.
133 */
134 void
sigexit(struct thread * td,int sig)135 sigexit(struct thread *td, int sig)
136 {
137 struct proc *p = td->td_proc;
138 int rv;
139 bool logexit;
140
141 PROC_LOCK_ASSERT(p, MA_OWNED);
142 proc_set_p2_wexit(p);
143
144 p->p_acflag |= AXSIG;
145 if ((p->p_flag2 & P2_LOGSIGEXIT_CTL) == 0)
146 logexit = kern_logsigexit != 0;
147 else
148 logexit = (p->p_flag2 & P2_LOGSIGEXIT_ENABLE) != 0;
149
150 /*
151 * We must be single-threading to generate a core dump. This
152 * ensures that the registers in the core file are up-to-date.
153 * Also, the ELF dump handler assumes that the thread list doesn't
154 * change out from under it.
155 *
156 * XXX If another thread attempts to single-thread before us
157 * (e.g. via fork()), we won't get a dump at all.
158 */
159 if (sig_do_core(sig) && thread_single(p, SINGLE_NO_EXIT) == 0) {
160 const char *err = NULL;
161
162 p->p_sig = sig;
163 /*
164 * Log signals which would cause core dumps
165 * (Log as LOG_INFO to appease those who don't want
166 * these messages.)
167 * XXX : Todo, as well as euid, write out ruid too
168 * Note that coredump() drops proc lock.
169 */
170 rv = coredump(td, &err);
171 if (rv == 0) {
172 MPASS(err == NULL);
173 sig |= WCOREFLAG;
174 } else if (err == NULL) {
175 switch (rv) {
176 case EFAULT:
177 err = "bad address";
178 break;
179 case EINVAL:
180 err = "invalild argument";
181 break;
182 case EFBIG:
183 err = "too large";
184 break;
185 default:
186 err = "other error";
187 break;
188 }
189 }
190 if (logexit)
191 log(LOG_INFO,
192 "pid %d (%s), jid %d, uid %d: exited on "
193 "signal %d (%s%s)\n", p->p_pid, p->p_comm,
194 p->p_ucred->cr_prison->pr_id,
195 td->td_ucred->cr_uid, sig &~ WCOREFLAG,
196 err != NULL ? "no core dump - " : "core dumped",
197 err != NULL ? err : "");
198 } else
199 PROC_UNLOCK(p);
200 exit1(td, 0, sig);
201 /* NOTREACHED */
202 }
203
204
205 /*
206 * Dump a process' core. The main routine does some
207 * policy checking, and creates the name of the coredump;
208 * then it passes on a vnode and a size limit to the process-specific
209 * coredump routine if there is one; if there _is not_ one, it returns
210 * ENOSYS; otherwise it returns the error from the process-specific routine.
211 */
212 static int
coredump(struct thread * td,const char ** errmsg)213 coredump(struct thread *td, const char **errmsg)
214 {
215 struct coredumper *iter, *chosen;
216 struct proc *p = td->td_proc;
217 struct rm_priotracker tracker;
218 off_t limit;
219 int error, priority;
220
221 PROC_LOCK_ASSERT(p, MA_OWNED);
222 MPASS((p->p_flag & P_HADTHREADS) == 0 || p->p_singlethread == td);
223
224 if (!do_coredump || (!sugid_coredump && (p->p_flag & P_SUGID) != 0) ||
225 (p->p_flag2 & P2_NOTRACE) != 0) {
226 PROC_UNLOCK(p);
227
228 if (!do_coredump)
229 *errmsg = "denied by kern.coredump";
230 else if ((p->p_flag2 & P2_NOTRACE) != 0)
231 *errmsg = "process has trace disabled";
232 else
233 *errmsg = "sugid process denied by kern.sugid_coredump";
234 return (EFAULT);
235 }
236
237 /*
238 * Note that the bulk of limit checking is done after
239 * the corefile is created. The exception is if the limit
240 * for corefiles is 0, in which case we don't bother
241 * creating the corefile at all. This layout means that
242 * a corefile is truncated instead of not being created,
243 * if it is larger than the limit.
244 */
245 limit = (off_t)lim_cur(td, RLIMIT_CORE);
246 if (limit == 0 || racct_get_available(p, RACCT_CORE) == 0) {
247 PROC_UNLOCK(p);
248 *errmsg = "coredumpsize limit is 0";
249 return (EFBIG);
250 }
251
252 rm_rlock(&coredump_rmlock, &tracker);
253 priority = -1;
254 chosen = NULL;
255 SLIST_FOREACH(iter, &coredumpers, cd_entry) {
256 if (iter->cd_probe == NULL) {
257 /*
258 * If we haven't found anything of a higher priority
259 * yet, we'll call this a GENERIC. Ideally, we want
260 * coredumper modules to include a probe function.
261 */
262 if (priority < 0) {
263 priority = COREDUMPER_GENERIC;
264 chosen = iter;
265 }
266
267 continue;
268 }
269
270 error = (*iter->cd_probe)(td);
271 if (error < 0)
272 continue;
273
274 /*
275 * Higher priority than previous options.
276 */
277 if (error > priority) {
278 priority = error;
279 chosen = iter;
280 }
281 }
282
283 /*
284 * Acquire our refcount before we drop the lock so that
285 * coredumper_unregister() can safely assume that the refcount will only
286 * go down once it's dropped the rmlock.
287 */
288 blockcount_acquire(&chosen->cd_refcount, 1);
289 rm_runlock(&coredump_rmlock, &tracker);
290
291 /* Currently, we always have the vnode dumper built in. */
292 MPASS(chosen != NULL);
293 error = ((*chosen->cd_handle)(td, limit));
294 PROC_LOCK_ASSERT(p, MA_NOTOWNED);
295
296 blockcount_release(&chosen->cd_refcount, 1);
297
298 return (error);
299 }
300