1350ffdd5SRobert Mustacchi /*
2350ffdd5SRobert Mustacchi * This file and its contents are supplied under the terms of the
3350ffdd5SRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4350ffdd5SRobert Mustacchi * You may only use this file in accordance with the terms of version
5350ffdd5SRobert Mustacchi * 1.0 of the CDDL.
6350ffdd5SRobert Mustacchi *
7350ffdd5SRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8350ffdd5SRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9350ffdd5SRobert Mustacchi * http://www.illumos.org/license/CDDL.
10350ffdd5SRobert Mustacchi */
11350ffdd5SRobert Mustacchi
12350ffdd5SRobert Mustacchi /*
13*88a8a2ffSRobert Mustacchi * Copyright 2021 Oxide Computer Company
14350ffdd5SRobert Mustacchi */
15350ffdd5SRobert Mustacchi
16350ffdd5SRobert Mustacchi #include <sys/proc.h>
17350ffdd5SRobert Mustacchi #include <c2/audit.h>
18350ffdd5SRobert Mustacchi #include <sys/procfs.h>
19350ffdd5SRobert Mustacchi #include <sys/core.h>
20350ffdd5SRobert Mustacchi
21350ffdd5SRobert Mustacchi /*
22350ffdd5SRobert Mustacchi * This function is meant to be a guaranteed abort that generates a core file
23350ffdd5SRobert Mustacchi * that allows up to 1k of data to enter into an elfnote in the process. This is
24350ffdd5SRobert Mustacchi * meant to insure that even in the face of other problems, this can get out.
25350ffdd5SRobert Mustacchi */
26350ffdd5SRobert Mustacchi
27350ffdd5SRobert Mustacchi void
upanic(void * addr,size_t len)28350ffdd5SRobert Mustacchi upanic(void *addr, size_t len)
29350ffdd5SRobert Mustacchi {
30350ffdd5SRobert Mustacchi kthread_t *t = curthread;
31350ffdd5SRobert Mustacchi proc_t *p = curproc;
32350ffdd5SRobert Mustacchi klwp_t *lwp = ttolwp(t);
33350ffdd5SRobert Mustacchi uint32_t auditing = AU_AUDITING();
34350ffdd5SRobert Mustacchi uint32_t upflag = P_UPF_PANICKED;
35350ffdd5SRobert Mustacchi void *buf;
36350ffdd5SRobert Mustacchi int code;
37350ffdd5SRobert Mustacchi
38350ffdd5SRobert Mustacchi /*
39350ffdd5SRobert Mustacchi * Before we worry about the data that the user has as a message, go
40350ffdd5SRobert Mustacchi * ahead and make sure we try and get all the other threads stopped.
41350ffdd5SRobert Mustacchi * That'll help us make sure that nothing else is going on and we don't
42350ffdd5SRobert Mustacchi * lose a race.
43350ffdd5SRobert Mustacchi */
44350ffdd5SRobert Mustacchi mutex_enter(&p->p_lock);
45350ffdd5SRobert Mustacchi lwp->lwp_cursig = SIGABRT;
46350ffdd5SRobert Mustacchi mutex_exit(&p->p_lock);
47350ffdd5SRobert Mustacchi
48350ffdd5SRobert Mustacchi proc_is_exiting(p);
49350ffdd5SRobert Mustacchi if (exitlwps(1) != 0) {
50350ffdd5SRobert Mustacchi mutex_enter(&p->p_lock);
51350ffdd5SRobert Mustacchi lwp_exit();
52350ffdd5SRobert Mustacchi }
53350ffdd5SRobert Mustacchi
54350ffdd5SRobert Mustacchi /*
55350ffdd5SRobert Mustacchi * Copy in the user data. We truncate it to PRUPANIC_BUFLEN no matter
56350ffdd5SRobert Mustacchi * what and ensure that the last data was set to zero.
57350ffdd5SRobert Mustacchi */
58350ffdd5SRobert Mustacchi if (addr != NULL && len > 0) {
59350ffdd5SRobert Mustacchi size_t copylen;
60350ffdd5SRobert Mustacchi
61350ffdd5SRobert Mustacchi upflag |= P_UPF_HAVEMSG;
62350ffdd5SRobert Mustacchi
63350ffdd5SRobert Mustacchi if (len >= PRUPANIC_BUFLEN) {
64350ffdd5SRobert Mustacchi copylen = PRUPANIC_BUFLEN;
65350ffdd5SRobert Mustacchi upflag |= P_UPF_TRUNCMSG;
66350ffdd5SRobert Mustacchi } else {
67350ffdd5SRobert Mustacchi copylen = len;
68350ffdd5SRobert Mustacchi }
69350ffdd5SRobert Mustacchi
70350ffdd5SRobert Mustacchi buf = kmem_zalloc(PRUPANIC_BUFLEN, KM_SLEEP);
71350ffdd5SRobert Mustacchi if (copyin(addr, buf, copylen) != 0) {
72350ffdd5SRobert Mustacchi upflag |= P_UPF_INVALMSG;
73350ffdd5SRobert Mustacchi upflag &= ~P_UPF_HAVEMSG;
74350ffdd5SRobert Mustacchi } else {
75350ffdd5SRobert Mustacchi mutex_enter(&p->p_lock);
76350ffdd5SRobert Mustacchi ASSERT3P(p->p_upanic, ==, NULL);
77350ffdd5SRobert Mustacchi p->p_upanic = buf;
78350ffdd5SRobert Mustacchi mutex_exit(&p->p_lock);
79350ffdd5SRobert Mustacchi }
80350ffdd5SRobert Mustacchi }
81350ffdd5SRobert Mustacchi
82350ffdd5SRobert Mustacchi mutex_enter(&p->p_lock);
83350ffdd5SRobert Mustacchi p->p_upanicflag = upflag;
84350ffdd5SRobert Mustacchi mutex_exit(&p->p_lock);
85350ffdd5SRobert Mustacchi
86*88a8a2ffSRobert Mustacchi /*
87*88a8a2ffSRobert Mustacchi * If we're auditing we need to finish the system call itself and then
88*88a8a2ffSRobert Mustacchi * begin the core dump.
89*88a8a2ffSRobert Mustacchi */
90*88a8a2ffSRobert Mustacchi if (auditing) {
91*88a8a2ffSRobert Mustacchi audit_finish(0, SYS_upanic, 0, NULL);
92350ffdd5SRobert Mustacchi audit_core_start(SIGABRT);
93*88a8a2ffSRobert Mustacchi }
94350ffdd5SRobert Mustacchi code = core(SIGABRT, B_FALSE);
95350ffdd5SRobert Mustacchi if (auditing) /* audit core dump */
96350ffdd5SRobert Mustacchi audit_core_finish(code ? CLD_KILLED : CLD_DUMPED);
97350ffdd5SRobert Mustacchi exit(code ? CLD_KILLED : CLD_DUMPED, SIGABRT);
98350ffdd5SRobert Mustacchi }
99