summaryrefslogtreecommitdiff
path: root/usr/src/uts/common
diff options
context:
space:
mode:
authorDan McDonald <danmcd@joyent.com>2020-11-17 14:48:44 -0500
committerDan McDonald <danmcd@joyent.com>2020-11-17 14:48:44 -0500
commit2d6415143e9c1044d04ebf846f72f232883413cb (patch)
tree555fae9f2f89b0c9a4d8c4bbd66b02b70ded9fc7 /usr/src/uts/common
parent5a1b3228538dfeb09e05cc2bdfad707ee4d698d7 (diff)
parent5a0af8165ce9590e7a18f1ef4f9badc4dd72c6e6 (diff)
downloadillumos-joyent-release-20201119.tar.gz
[illumos-gate merge]release-20201119
commit 5a0af8165ce9590e7a18f1ef4f9badc4dd72c6e6 13274 enable -fstack-protector-strong by default in user land commit 6a817834d81cc75ce12d0d393320837b1fec1e85 5788 Want support for GCC's stack protector in libc commit 350ffdd54baf880f440ddf9697666e283894ded1 13273 want upanic(2) commit 7fdea60d55a95f0e46066fd021c4ef1b1321bafc 13300 mlxcx_cq_setup() doesn't take required locks for ASSERTs Merge notes: - Manifest changes to match package changes (including shipping libssp_ns.a) - Modified lx_vdso tools to not include SSP, to match other build-only tools.
Diffstat (limited to 'usr/src/uts/common')
-rw-r--r--usr/src/uts/common/Makefile.files1
-rw-r--r--usr/src/uts/common/exec/elf/elf_notes.c38
-rw-r--r--usr/src/uts/common/io/mlxcx/mlxcx_ring.c2
-rw-r--r--usr/src/uts/common/os/exit.c10
-rw-r--r--usr/src/uts/common/os/sysent.c6
-rw-r--r--usr/src/uts/common/os/upanic.c92
-rw-r--r--usr/src/uts/common/sys/ccompile.h1
-rw-r--r--usr/src/uts/common/sys/elf.h4
-rw-r--r--usr/src/uts/common/sys/proc.h11
-rw-r--r--usr/src/uts/common/sys/procfs.h15
-rw-r--r--usr/src/uts/common/sys/syscall.h46
11 files changed, 201 insertions, 25 deletions
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index 752fe56100..374fa41cee 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -387,6 +387,7 @@ GENUNIX_OBJS += \
uname.o \
unix_bb.o \
unlink.o \
+ upanic.o \
urw.o \
utime.o \
utssys.o \
diff --git a/usr/src/uts/common/exec/elf/elf_notes.c b/usr/src/uts/common/exec/elf/elf_notes.c
index 06f9ceb633..a88250b00f 100644
--- a/usr/src/uts/common/exec/elf/elf_notes.c
+++ b/usr/src/uts/common/exec/elf/elf_notes.c
@@ -164,6 +164,13 @@ setup_note_header(Phdr *v, proc_t *p)
v[0].p_filesz += nlwp * sizeof (Note)
+ nlwp * roundup(sizeof (asrset_t), sizeof (Word));
#endif /* __sparc */
+
+ mutex_enter(&p->p_lock);
+ if ((p->p_upanicflag & P_UPF_PANICKED) != 0) {
+ v[0].p_filesz += sizeof (Note) +
+ roundup(sizeof (prupanic_t), sizeof (Word));
+ }
+ mutex_exit(&p->p_lock);
}
int
@@ -186,6 +193,7 @@ write_elfnotes(proc_t *p, int sig, vnode_t *vp, offset_t offset,
priv_impl_info_t prinfo;
struct utsname uts;
prsecflags_t psecflags;
+ prupanic_t upanic;
} *bigwad;
size_t xregsize = prhasx(p)? prgetprxregsize(p) : 0;
@@ -599,6 +607,36 @@ write_elfnotes(proc_t *p, int sig, vnode_t *vp, offset_t offset,
}
ASSERT(nlwp == 0);
+ /*
+ * If a upanic occurred, add a note for it.
+ */
+ mutex_enter(&p->p_lock);
+ if ((p->p_upanicflag & P_UPF_PANICKED) != 0) {
+ bzero(&bigwad->upanic, sizeof (prupanic_t));
+ bigwad->upanic.pru_version = PRUPANIC_VERSION_1;
+ if ((p->p_upanicflag & P_UPF_INVALMSG) != 0) {
+ bigwad->upanic.pru_flags |= PRUPANIC_FLAG_MSG_ERROR;
+ }
+
+ if ((p->p_upanicflag & P_UPF_TRUNCMSG) != 0) {
+ bigwad->upanic.pru_flags |= PRUPANIC_FLAG_MSG_TRUNC;
+ }
+
+ if ((p->p_upanicflag & P_UPF_HAVEMSG) != 0) {
+ bigwad->upanic.pru_flags |= PRUPANIC_FLAG_MSG_VALID;
+ bcopy(p->p_upanic, bigwad->upanic.pru_data,
+ PRUPANIC_BUFLEN);
+ }
+
+ error = elfnote(vp, &offset, NT_UPANIC, sizeof (prupanic_t),
+ &bigwad->upanic, rlimit, credp);
+ if (error != 0) {
+ mutex_exit(&p->p_lock);
+ goto done;
+ }
+ }
+ mutex_exit(&p->p_lock);
+
done:
kmem_free(bigwad, bigsize);
return (error);
diff --git a/usr/src/uts/common/io/mlxcx/mlxcx_ring.c b/usr/src/uts/common/io/mlxcx/mlxcx_ring.c
index 17a09b9cae..6ce37ef1a0 100644
--- a/usr/src/uts/common/io/mlxcx/mlxcx_ring.c
+++ b/usr/src/uts/common/io/mlxcx/mlxcx_ring.c
@@ -378,12 +378,14 @@ mlxcx_cq_setup(mlxcx_t *mlxp, mlxcx_event_queue_t *eq,
mutex_exit(&cq->mlcq_mtx);
mutex_enter(&eq->mleq_mtx);
+ mutex_enter(&cq->mlcq_arm_mtx);
mutex_enter(&cq->mlcq_mtx);
ASSERT0(cq->mlcq_state & MLXCX_CQ_EQAVL);
avl_add(&eq->mleq_cqs, cq);
atomic_or_uint(&cq->mlcq_state, MLXCX_CQ_EQAVL);
mlxcx_arm_cq(mlxp, cq);
mutex_exit(&cq->mlcq_mtx);
+ mutex_exit(&cq->mlcq_arm_mtx);
mutex_exit(&eq->mleq_mtx);
*cqp = cq;
diff --git a/usr/src/uts/common/os/exit.c b/usr/src/uts/common/os/exit.c
index 06e0117cd6..5563c0f4ab 100644
--- a/usr/src/uts/common/os/exit.c
+++ b/usr/src/uts/common/os/exit.c
@@ -22,6 +22,7 @@
/*
* Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2018 Joyent, Inc.
+ * Copyright 2020 Oxide Computer Company
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -71,6 +72,7 @@
#include <sys/pool.h>
#include <sys/sdt.h>
#include <sys/corectl.h>
+#include <sys/core.h>
#include <sys/brand.h>
#include <sys/libc_kernel.h>
@@ -600,6 +602,14 @@ proc_exit(int why, int what)
}
/*
+ * If we had generated any upanic(2) state, free that now.
+ */
+ if (p->p_upanic != NULL) {
+ kmem_free(p->p_upanic, PRUPANIC_BUFLEN);
+ p->p_upanic = NULL;
+ }
+
+ /*
* Remove any fpollinfo_t's for this (last) thread from our file
* descriptors so closeall() can ASSERT() that they're all gone.
*/
diff --git a/usr/src/uts/common/os/sysent.c b/usr/src/uts/common/os/sysent.c
index fb64000e4d..be45b7ad8f 100644
--- a/usr/src/uts/common/os/sysent.c
+++ b/usr/src/uts/common/os/sysent.c
@@ -25,6 +25,7 @@
* Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved.
* Copyright 2016 Joyent, Inc.
* Copyright (c) 2018, Joyent, Inc.
+ * Copyright 2020 Oxide Computer Company
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -330,6 +331,7 @@ int setsockopt(int, int, int, void *, socklen_t *, int);
int sockconfig(int, void *, void *, void *, void *);
ssize_t sendfilev(int, int, const struct sendfilevec *, int, size_t *);
ssize_t getrandom(void *, size_t, unsigned int);
+void upanic(void *, size_t);
typedef int64_t (*llfcn_t)(); /* for casting one-word returns */
@@ -583,7 +585,7 @@ struct sysent sysent[NSYSCALL] =
/* 122 */ SYSENT_CL("writev", writev, 3),
/* 123 */ SYSENT_CL("preadv", preadv, 5),
/* 124 */ SYSENT_CL("pwritev", pwritev, 5),
- /* 125 */ SYSENT_LOADABLE(), /* (was fxstat) */
+ /* 125 */ SYSENT_CI("upanic", upanic, 2),
/* 126 */ SYSENT_CL("getrandom", getrandom, 3),
/* 127 */ SYSENT_CI("mmapobj", mmapobjsys, 5),
/* 128 */ IF_LP64(
@@ -948,7 +950,7 @@ struct sysent sysent32[NSYSCALL] =
/* 122 */ SYSENT_CI("writev", writev32, 3),
/* 123 */ SYSENT_CI("preadv", preadv, 5),
/* 124 */ SYSENT_CI("pwritev", pwritev, 5),
- /* 125 */ SYSENT_LOADABLE32(), /* was fxstat32 */
+ /* 125 */ SYSENT_CI("upanic", upanic, 2),
/* 126 */ SYSENT_CI("getrandom", getrandom, 3),
/* 127 */ SYSENT_CI("mmapobj", mmapobjsys, 5),
/* 128 */ SYSENT_CI("setrlimit", setrlimit32, 2),
diff --git a/usr/src/uts/common/os/upanic.c b/usr/src/uts/common/os/upanic.c
new file mode 100644
index 0000000000..8acb9440f2
--- /dev/null
+++ b/usr/src/uts/common/os/upanic.c
@@ -0,0 +1,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);
+}
diff --git a/usr/src/uts/common/sys/ccompile.h b/usr/src/uts/common/sys/ccompile.h
index de0031d6b0..e687fd99a3 100644
--- a/usr/src/uts/common/sys/ccompile.h
+++ b/usr/src/uts/common/sys/ccompile.h
@@ -160,6 +160,7 @@ extern "C" {
#define __unused __sun_attr__((__unused__))
#define __used __attribute__((__used__))
#define __weak_symbol __attribute__((__weak__))
+#define __HIDDEN __attribute__((visibility("hidden")))
#ifdef __cplusplus
}
diff --git a/usr/src/uts/common/sys/elf.h b/usr/src/uts/common/sys/elf.h
index 1a2ca397ef..384c6daf99 100644
--- a/usr/src/uts/common/sys/elf.h
+++ b/usr/src/uts/common/sys/elf.h
@@ -21,6 +21,7 @@
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
* Copyright (c) 2018, Joyent, Inc.
+ * Copyright 2020 Oxide Computer Company
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
@@ -1018,7 +1019,8 @@ typedef Elf64_Word Elf64_Capchain;
#define NT_SPYMASTER 23 /* psinfo_t for agent LWP spymaster */
#define NT_SECFLAGS 24 /* process security-flags */
#define NT_LWPNAME 25 /* prlwpname_t */
-#define NT_NUM 25
+#define NT_UPANIC 26 /* prupanic_t */
+#define NT_NUM 26
#ifdef _KERNEL
diff --git a/usr/src/uts/common/sys/proc.h b/usr/src/uts/common/sys/proc.h
index 757bbc87e7..bb6f62f83f 100644
--- a/usr/src/uts/common/sys/proc.h
+++ b/usr/src/uts/common/sys/proc.h
@@ -22,6 +22,7 @@
/*
* Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2018 Joyent, Inc.
+ * Copyright 2020 Oxide Computer Company
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -355,6 +356,8 @@ typedef struct proc {
kcondvar_t p_poolcv; /* synchronization with pools */
uint_t p_poolcnt; /* # threads inside pool barrier */
uint_t p_poolflag; /* pool-related flags (see below) */
+ uint_t p_upanicflag; /* upanic-related flags (see below) */
+ void *p_upanic; /* optional upanic data */
uintptr_t p_portcnt; /* event ports counter */
struct zone *p_zone; /* zone in which process lives */
struct vnode *p_execdir; /* directory that p_exec came from */
@@ -524,6 +527,14 @@ extern struct pid pid0; /* p0's pid */
#define PBWAIT 0x0001 /* process should wait outside fork/exec/exit */
#define PEXITED 0x0002 /* process exited and about to become zombie */
+/*
+ * p_upanicflag codes
+ */
+#define P_UPF_PANICKED 0x0001
+#define P_UPF_HAVEMSG 0x0002
+#define P_UPF_TRUNCMSG 0x0004
+#define P_UPF_INVALMSG 0x0008
+
/* Macro to convert proc pointer to a user block pointer */
#define PTOU(p) (&(p)->p_user)
diff --git a/usr/src/uts/common/sys/procfs.h b/usr/src/uts/common/sys/procfs.h
index 517f2551b4..3d6760a7b4 100644
--- a/usr/src/uts/common/sys/procfs.h
+++ b/usr/src/uts/common/sys/procfs.h
@@ -678,6 +678,21 @@ typedef struct prheader {
(((unsigned)((flag)-1) < 32*sizeof (*(sp))/sizeof (uint32_t)) && \
(((uint32_t *)(sp))[((flag)-1)/32] & (1U<<(((flag)-1)%32))))
+/*
+ * Core file upanic NT_UPANIC structure.
+ */
+#define PRUPANIC_VERSION_1 1
+#define PRUPANIC_VERSION_CURRENT PRUPANIC_VERSION_1
+#define PRUPANIC_FLAG_MSG_VALID 0x01
+#define PRUPANIC_FLAG_MSG_ERROR 0x02
+#define PRUPANIC_FLAG_MSG_TRUNC 0x04
+#define PRUPANIC_BUFLEN 1024
+typedef struct prupanic {
+ uint32_t pru_version;
+ uint32_t pru_flags;
+ uint8_t pru_data[PRUPANIC_BUFLEN];
+} prupanic_t;
+
#if defined(_SYSCALL32)
/*
diff --git a/usr/src/uts/common/sys/syscall.h b/usr/src/uts/common/sys/syscall.h
index 8709f98c26..cd4f5445b0 100644
--- a/usr/src/uts/common/sys/syscall.h
+++ b/usr/src/uts/common/sys/syscall.h
@@ -24,6 +24,7 @@
* Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2015, Joyent, Inc. All rights reserved.
+ * Copyright 2020 Oxide Computer Company
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -168,38 +169,38 @@ extern "C" {
#define SYS_tasksys 70
/*
* subcodes:
- * settaskid(...) :: tasksys(0, ...)
- * gettaskid(...) :: tasksys(1, ...)
- * getprojid(...) :: tasksys(2, ...)
+ * settaskid(...) :: tasksys(0, ...)
+ * gettaskid(...) :: tasksys(1, ...)
+ * getprojid(...) :: tasksys(2, ...)
*/
#define SYS_acctctl 71
#define SYS_exacctsys 72
/*
* subcodes:
- * getacct(...) :: exacct(0, ...)
- * putacct(...) :: exacct(1, ...)
- * wracct(...) :: exacct(2, ...)
+ * getacct(...) :: exacct(0, ...)
+ * putacct(...) :: exacct(1, ...)
+ * wracct(...) :: exacct(2, ...)
*/
#define SYS_getpagesizes 73
/*
* subcodes:
* getpagesizes2(...) :: getpagesizes(0, ...)
- * getpagesizes(...) :: getpagesizes(1, ...) legacy
+ * getpagesizes(...) :: getpagesizes(1, ...) legacy
*/
#define SYS_rctlsys 74
/*
* subcodes:
- * getrctl(...) :: rctlsys(0, ...)
- * setrctl(...) :: rctlsys(1, ...)
- * rctllist(...) :: rctlsys(2, ...)
- * rctlctl(...) :: rctlsys(3, ...)
+ * getrctl(...) :: rctlsys(0, ...)
+ * setrctl(...) :: rctlsys(1, ...)
+ * rctllist(...) :: rctlsys(2, ...)
+ * rctlctl(...) :: rctlsys(3, ...)
*/
#define SYS_sidsys 75
/*
* subcodes:
- * allocids(...) :: sidsys(0, ...)
- * idmap_reg(...) :: sidsys(1, ...)
- * idmap_unreg(...) :: sidsys(2, ...)
+ * allocids(...) :: sidsys(0, ...)
+ * idmap_reg(...) :: sidsys(1, ...)
+ * idmap_unreg(...) :: sidsys(2, ...)
*/
#define SYS_lwp_park 77
/*
@@ -213,8 +214,8 @@ extern "C" {
#define SYS_sendfilev 78
/*
* subcodes :
- * sendfilev() :: sendfilev(0, ...)
- * sendfilev64() :: sendfilev(1, ...)
+ * sendfilev() :: sendfilev(0, ...)
+ * sendfilev64() :: sendfilev(1, ...)
*/
#define SYS_rmdir 79
#define SYS_mkdir 80
@@ -222,11 +223,11 @@ extern "C" {
#define SYS_privsys 82
/*
* subcodes:
- * setppriv(...) :: privsys(0, ...)
- * getppriv(...) :: privsys(1, ...)
- * getimplinfo(...) :: privsys(2, ...)
- * setpflags(...) :: privsys(3, ...)
- * getpflags(...) :: privsys(4, ...)
+ * setppriv(...) :: privsys(0, ...)
+ * getppriv(...) :: privsys(1, ...)
+ * getimplinfo(...) :: privsys(2, ...)
+ * setpflags(...) :: privsys(3, ...)
+ * getpflags(...) :: privsys(4, ...)
* issetugid(); :: privsys(5)
*/
#define SYS_ucredsys 83
@@ -297,6 +298,7 @@ extern "C" {
#define SYS_writev 122
#define SYS_preadv 123
#define SYS_pwritev 124
+#define SYS_upanic 125
#define SYS_getrandom 126
#define SYS_mmapobj 127
#define SYS_setrlimit 128
@@ -368,7 +370,7 @@ extern "C" {
#define SYS_meminfosys SYS_lgrpsys
/*
* subcodes:
- * meminfo(...) :: meminfosys(MISYS_MEMINFO, ...)
+ * meminfo(...) :: meminfosys(MISYS_MEMINFO, ...)
*/
#define SYS_rusagesys 181
/*