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