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 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 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 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 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 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