1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2020 Oxide Computer Company 14 */ 15 16 #include <sys/proc.h> 17 #include <c2/audit.h> 18 #include <sys/procfs.h> 19 #include <sys/core.h> 20 21 /* 22 * This function is meant to be a guaranteed abort that generates a core file 23 * that allows up to 1k of data to enter into an elfnote in the process. This is 24 * meant to insure that even in the face of other problems, this can get out. 25 */ 26 27 void 28 upanic(void *addr, size_t len) 29 { 30 kthread_t *t = curthread; 31 proc_t *p = curproc; 32 klwp_t *lwp = ttolwp(t); 33 uint32_t auditing = AU_AUDITING(); 34 uint32_t upflag = P_UPF_PANICKED; 35 void *buf; 36 int code; 37 38 /* 39 * Before we worry about the data that the user has as a message, go 40 * ahead and make sure we try and get all the other threads stopped. 41 * That'll help us make sure that nothing else is going on and we don't 42 * lose a race. 43 */ 44 mutex_enter(&p->p_lock); 45 lwp->lwp_cursig = SIGABRT; 46 mutex_exit(&p->p_lock); 47 48 proc_is_exiting(p); 49 if (exitlwps(1) != 0) { 50 mutex_enter(&p->p_lock); 51 lwp_exit(); 52 } 53 54 /* 55 * Copy in the user data. We truncate it to PRUPANIC_BUFLEN no matter 56 * what and ensure that the last data was set to zero. 57 */ 58 if (addr != NULL && len > 0) { 59 size_t copylen; 60 61 upflag |= P_UPF_HAVEMSG; 62 63 if (len >= PRUPANIC_BUFLEN) { 64 copylen = PRUPANIC_BUFLEN; 65 upflag |= P_UPF_TRUNCMSG; 66 } else { 67 copylen = len; 68 } 69 70 buf = kmem_zalloc(PRUPANIC_BUFLEN, KM_SLEEP); 71 if (copyin(addr, buf, copylen) != 0) { 72 upflag |= P_UPF_INVALMSG; 73 upflag &= ~P_UPF_HAVEMSG; 74 } else { 75 mutex_enter(&p->p_lock); 76 ASSERT3P(p->p_upanic, ==, NULL); 77 p->p_upanic = buf; 78 mutex_exit(&p->p_lock); 79 } 80 } 81 82 mutex_enter(&p->p_lock); 83 p->p_upanicflag = upflag; 84 mutex_exit(&p->p_lock); 85 86 if (auditing) /* audit core dump */ 87 audit_core_start(SIGABRT); 88 code = core(SIGABRT, B_FALSE); 89 if (auditing) /* audit core dump */ 90 audit_core_finish(code ? CLD_KILLED : CLD_DUMPED); 91 exit(code ? CLD_KILLED : CLD_DUMPED, SIGABRT); 92 } 93