Page MenuHomeFreeBSD

D32505.diff
No OneTemporary

D32505.diff

diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -122,6 +122,7 @@
readdir-compat11.c \
readpassphrase.c \
rewinddir.c \
+ rseq_abi.c \
scandir.c \
scandir_b.c \
scandir-compat11.c \
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -451,6 +451,7 @@
versionsort;
__cpuset_alloc;
__cpuset_free;
+ __rseq_abi;
};
FBSD_1.8 {
@@ -612,4 +613,6 @@
__getcontextx_size;
__makecontext;
__uexterr_format;
+
+ __rseq_abi_init;
};
diff --git a/lib/libc/gen/rseq_abi.c b/lib/libc/gen/rseq_abi.c
new file mode 100644
--- /dev/null
+++ b/lib/libc/gen/rseq_abi.c
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 2021 The FreeBSD Foundation
+ *
+ * This software were developed by Konstantin Belousov <kib@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/auxv.h>
+#include <sys/rseq.h>
+#include <sched.h>
+#include "libc_private.h"
+
+_Thread_local volatile struct rseq __rseq_abi __weak_symbol;
+
+static void __main_rseq_abi_init(void) __attribute__((__constructor__,
+ __used__));
+static void
+__main_rseq_abi_init(void)
+{
+ __rseq_abi_init();
+}
+
+void
+__rseq_abi_init(void)
+{
+ int bsdflags;
+
+ if (_elf_aux_info(AT_BSDFLAGS, &bsdflags, sizeof(bsdflags)) != 0 ||
+ (bsdflags & ELF_BSDF_RSEQ1) == 0)
+ return;
+ __rseq_abi.cpu_id_start = sched_getcpu();
+ rseq(&__rseq_abi, sizeof(__rseq_abi), 0, 0/* XXXKIB */);
+}
diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h
--- a/lib/libc/include/libc_private.h
+++ b/lib/libc/include/libc_private.h
@@ -384,4 +384,6 @@
int __uexterr_format(const struct uexterror *ue, char *buf, size_t bufsz);
int __libc_uexterr_gettext(char *buf, size_t bufsz);
+void __rseq_abi_init(void);
+
#endif /* _LIBC_PRIVATE_H_ */
diff --git a/lib/libsys/Symbol.sys.map b/lib/libsys/Symbol.sys.map
--- a/lib/libsys/Symbol.sys.map
+++ b/lib/libsys/Symbol.sys.map
@@ -394,6 +394,7 @@
pdrfork;
pdrfork_thread;
renameat2;
+ rseq;
};
FBSDprivate_1.0 {
diff --git a/lib/libsys/_libsys.h b/lib/libsys/_libsys.h
--- a/lib/libsys/_libsys.h
+++ b/lib/libsys/_libsys.h
@@ -475,6 +475,7 @@
typedef int (__sys_pdrfork_t)(int *, int, int);
typedef int (__sys_pdwait_t)(int, int *, int, struct __wrusage *, struct __siginfo *);
typedef int (__sys_renameat2_t)(int, const char *, int, const char *, int);
+typedef int (__sys_rseq_t)(void *, uint32_t, int, uint32_t);
_Noreturn void __sys__exit(int rval);
int __sys_fork(void);
@@ -885,6 +886,7 @@
int __sys_pdrfork(int * fdp, int pdflags, int rfflags);
int __sys_pdwait(int fd, int * status, int options, struct __wrusage * wrusage, struct __siginfo * info);
int __sys_renameat2(int oldfd, const char * old, int newfd, const char * new, int flags);
+int __sys_rseq(void * rseq, uint32_t rseqlen, int flags, uint32_t sig);
__END_DECLS
#endif /* __LIBSYS_H_ */
diff --git a/lib/libsys/syscalls.map b/lib/libsys/syscalls.map
--- a/lib/libsys/syscalls.map
+++ b/lib/libsys/syscalls.map
@@ -825,4 +825,6 @@
__sys_pdwait;
_renameat2;
__sys_renameat2;
+ _rseq;
+ __sys_rseq;
};
diff --git a/lib/libthr/thread/thr_create.c b/lib/libthr/thread/thr_create.c
--- a/lib/libthr/thread/thr_create.c
+++ b/lib/libthr/thread/thr_create.c
@@ -295,6 +295,8 @@
if (__getosreldate() >= P_OSREL_EXTERRCTL)
exterrctl(EXTERRCTL_ENABLE, 0, &curthread->uexterr);
+ __rseq_abi_init();
+
/* Run the current thread's start routine with argument: */
_pthread_exit(curthread->start_routine(curthread->arg));
diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h
--- a/sys/compat/freebsd32/freebsd32_syscall.h
+++ b/sys/compat/freebsd32/freebsd32_syscall.h
@@ -520,4 +520,5 @@
#define FREEBSD32_SYS_pdrfork 600
#define FREEBSD32_SYS_freebsd32_pdwait 601
#define FREEBSD32_SYS_renameat2 602
-#define FREEBSD32_SYS_MAXSYSCALL 603
+#define FREEBSD32_SYS_rseq 603
+#define FREEBSD32_SYS_MAXSYSCALL 604
diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c
--- a/sys/compat/freebsd32/freebsd32_syscalls.c
+++ b/sys/compat/freebsd32/freebsd32_syscalls.c
@@ -608,4 +608,5 @@
"pdrfork", /* 600 = pdrfork */
"freebsd32_pdwait", /* 601 = freebsd32_pdwait */
"renameat2", /* 602 = renameat2 */
+ "rseq", /* 603 = rseq */
};
diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c
--- a/sys/compat/freebsd32/freebsd32_sysent.c
+++ b/sys/compat/freebsd32/freebsd32_sysent.c
@@ -311,7 +311,7 @@
{ .sy_narg = AS(ffclock_getcounter_args), .sy_call = (sy_call_t *)sys_ffclock_getcounter, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 241 = ffclock_getcounter */
{ .sy_narg = AS(freebsd32_ffclock_setestimate_args), .sy_call = (sy_call_t *)freebsd32_ffclock_setestimate, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 242 = freebsd32_ffclock_setestimate */
{ .sy_narg = AS(freebsd32_ffclock_getestimate_args), .sy_call = (sy_call_t *)freebsd32_ffclock_getestimate, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 243 = freebsd32_ffclock_getestimate */
- { .sy_narg = AS(freebsd32_clock_nanosleep_args), .sy_call = (sy_call_t *)freebsd32_clock_nanosleep, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 244 = freebsd32_clock_nanosleep */
+ { .sy_narg = AS(freebsd32_clock_nanosleep_args), .sy_call = (sy_call_t *)freebsd32_clock_nanosleep, .sy_auevent = AUE_NULL, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 244 = freebsd32_clock_nanosleep */
{ .sy_narg = 0, .sy_call = (sy_call_t *)nosys, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_ABSENT }, /* 245 = reserved for local use */
{ .sy_narg = 0, .sy_call = (sy_call_t *)nosys, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_ABSENT }, /* 246 = reserved for local use */
{ .sy_narg = AS(freebsd32_clock_getcpuclockid2_args), .sy_call = (sy_call_t *)freebsd32_clock_getcpuclockid2, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 247 = freebsd32_clock_getcpuclockid2 */
@@ -670,4 +670,5 @@
{ .sy_narg = AS(pdrfork_args), .sy_call = (sy_call_t *)sys_pdrfork, .sy_auevent = AUE_PDRFORK, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 600 = pdrfork */
{ .sy_narg = AS(freebsd32_pdwait_args), .sy_call = (sy_call_t *)freebsd32_pdwait, .sy_auevent = AUE_PDWAIT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 601 = freebsd32_pdwait */
{ .sy_narg = AS(renameat2_args), .sy_call = (sy_call_t *)sys_renameat2, .sy_auevent = AUE_RENAMEAT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 602 = renameat2 */
+ { .sy_narg = AS(rseq_args), .sy_call = (sy_call_t *)sys_rseq, .sy_auevent = AUE_NULL, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 603 = rseq */
};
diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c
--- a/sys/compat/freebsd32/freebsd32_systrace_args.c
+++ b/sys/compat/freebsd32/freebsd32_systrace_args.c
@@ -3458,6 +3458,16 @@
*n_args = 5;
break;
}
+ /* rseq */
+ case 603: {
+ struct rseq_args *p = params;
+ uarg[a++] = (intptr_t)p->rseq; /* void * */
+ uarg[a++] = p->rseqlen; /* uint32_t */
+ iarg[a++] = p->flags; /* int */
+ uarg[a++] = p->sig; /* uint32_t */
+ *n_args = 4;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -9347,6 +9357,25 @@
break;
};
break;
+ /* rseq */
+ case 603:
+ switch (ndx) {
+ case 0:
+ p = "userland void *";
+ break;
+ case 1:
+ p = "uint32_t";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -11280,6 +11309,11 @@
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* rseq */
+ case 603:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
diff --git a/sys/conf/files b/sys/conf/files
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -3907,6 +3907,7 @@
kern/kern_rctl.c standard
kern/kern_resource.c standard
kern/kern_rmlock.c standard
+kern/kern_rseq.c standard
kern/kern_rwlock.c standard
kern/kern_sdt.c optional kdtrace_hooks
kern/kern_sema.c standard
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -222,6 +222,11 @@
CTLFLAG_RWTUN, &__elfN(sigfastblock), 0,
"enable sigfastblock for new processes");
+static int __elfN(rseq1) = 1;
+SYSCTL_INT(__CONCAT(_kern_elf, __ELF_WORD_SIZE), OID_AUTO, rseq1,
+ CTLFLAG_RWTUN, &__elfN(rseq1), 0,
+ "enable rseq v1 ABI for new processes");
+
static bool __elfN(allow_wx) = true;
SYSCTL_BOOL(ELF_NODE_OID, OID_AUTO, allow_wx,
CTLFLAG_RWTUN, &__elfN(allow_wx), 0,
@@ -1533,6 +1538,7 @@
oc = atomic_load_int(&vm_overcommit);
bsdflags |= (oc & (SWAP_RESERVE_FORCE_ON | SWAP_RESERVE_RLIMIT_ON)) !=
0 ? ELF_BSDF_VMNOOVERCOMMIT : 0;
+ bsdflags |= __elfN(rseq1) ? ELF_BSDF_RSEQ1 : 0;
AUXARGS_ENTRY(pos, AT_BSDFLAGS, bsdflags);
AUXARGS_ENTRY(pos, AT_ARGC, imgp->args->argc);
AUXARGS_ENTRY_PTR(pos, AT_ARGV, imgp->argv);
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
--- a/sys/kern/init_sysent.c
+++ b/sys/kern/init_sysent.c
@@ -310,7 +310,7 @@
{ .sy_narg = AS(ffclock_getcounter_args), .sy_call = (sy_call_t *)sys_ffclock_getcounter, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 241 = ffclock_getcounter */
{ .sy_narg = AS(ffclock_setestimate_args), .sy_call = (sy_call_t *)sys_ffclock_setestimate, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 242 = ffclock_setestimate */
{ .sy_narg = AS(ffclock_getestimate_args), .sy_call = (sy_call_t *)sys_ffclock_getestimate, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 243 = ffclock_getestimate */
- { .sy_narg = AS(clock_nanosleep_args), .sy_call = (sy_call_t *)sys_clock_nanosleep, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 244 = clock_nanosleep */
+ { .sy_narg = AS(clock_nanosleep_args), .sy_call = (sy_call_t *)sys_clock_nanosleep, .sy_auevent = AUE_NULL, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 244 = clock_nanosleep */
{ .sy_narg = 0, .sy_call = (sy_call_t *)nosys, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_ABSENT }, /* 245 = reserved for local use */
{ .sy_narg = 0, .sy_call = (sy_call_t *)nosys, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_ABSENT }, /* 246 = reserved for local use */
{ .sy_narg = AS(clock_getcpuclockid2_args), .sy_call = (sy_call_t *)sys_clock_getcpuclockid2, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 247 = clock_getcpuclockid2 */
@@ -669,4 +669,5 @@
{ .sy_narg = AS(pdrfork_args), .sy_call = (sy_call_t *)sys_pdrfork, .sy_auevent = AUE_PDRFORK, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 600 = pdrfork */
{ .sy_narg = AS(pdwait_args), .sy_call = (sy_call_t *)sys_pdwait, .sy_auevent = AUE_PDWAIT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 601 = pdwait */
{ .sy_narg = AS(renameat2_args), .sy_call = (sy_call_t *)sys_renameat2, .sy_auevent = AUE_RENAMEAT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 602 = renameat2 */
+ { .sy_narg = AS(rseq_args), .sy_call = (sy_call_t *)sys_rseq, .sy_auevent = AUE_NULL, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 603 = rseq */
};
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -829,6 +829,7 @@
/* STOPs are no longer ignored, arrange for AST */
signotify(td);
}
+ td->td_rseq_abi = NULL;
if ((imgp->sysent->sv_setid_allowed != NULL &&
!(*imgp->sysent->sv_setid_allowed)(td, imgp)) ||
diff --git a/sys/kern/kern_membarrier.c b/sys/kern/kern_membarrier.c
--- a/sys/kern/kern_membarrier.c
+++ b/sys/kern/kern_membarrier.c
@@ -52,8 +52,22 @@
MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED | \
MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE | \
MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE | \
+ MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ | \
+ MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ | \
MEMBARRIER_CMD_GET_REGISTRATIONS)
+static void
+membarrier_action_rseq(void *arg __unused)
+{
+ struct thread *td;
+
+ td = curthread;
+ thread_lock(td);
+ ast_sched_locked(td, TDA_RSEQ);
+ td->td_flags |= TDF_RSEQ_MB;
+ thread_unlock(td);
+}
+
static void
membarrier_action_seqcst(void *arg __unused)
{
@@ -226,6 +240,29 @@
}
break;
+ case MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ:
+ if ((td->td_proc->p_flag2 & P2_MEMBAR_PRIVE_RSEQ) == 0) {
+ error = EPERM;
+ break;
+ }
+ pmap_active_cpus(vmspace_pmap(p->p_vmspace), &cs);
+ if ((flags & MEMBARRIER_CMD_FLAG_CPU) != 0) {
+ if (!CPU_ISSET(cpu_id, &cs))
+ break;
+ CPU_ZERO(&cs);
+ CPU_SET(cpu_id, &cs);
+ }
+ do_membarrier_ipi(&cs, membarrier_action_rseq);
+ break;
+
+ case MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ:
+ if ((p->p_flag2 & P2_MEMBAR_PRIVE_RSEQ) == 0) {
+ PROC_LOCK(p);
+ p->p_flag2 |= P2_MEMBAR_PRIVE_RSEQ;
+ PROC_UNLOCK(p);
+ }
+ break;
+
case MEMBARRIER_CMD_GET_REGISTRATIONS:
res = 0;
if ((f & P2_MEMBAR_GLOBE) != 0)
diff --git a/sys/kern/kern_rseq.c b/sys/kern/kern_rseq.c
new file mode 100644
--- /dev/null
+++ b/sys/kern/kern_rseq.c
@@ -0,0 +1,283 @@
+/*-
+ * Copyright (c) 2021 The FreeBSD Foundation
+ *
+ * This software were developed by Konstantin Belousov <kib@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/sysproto.h>
+#include <sys/rseq.h>
+
+static void
+rseq_inactivate(struct thread *td)
+{
+ td->td_rseq_abi = NULL;
+}
+
+static void
+rseq_inactivate_sig(struct thread *td, void *addr, int si_code)
+{
+ ksiginfo_t ksi;
+
+ rseq_inactivate(td);
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = SIGSEGV;
+ ksi.ksi_code = si_code;
+ ksi.ksi_trapno = 0;
+ ksi.ksi_addr = addr;
+ trapsignal(td, &ksi);
+}
+
+static bool
+rseq_check_signature(struct thread *td, const struct rseq_cs *rc)
+{
+ void *usig_addr;
+ uint32_t usig;
+ int error;
+
+ usig_addr = (void *)(rc->abort_ip - sizeof(usig));
+ error = copyin(usig_addr, &usig, sizeof(usig));
+ if (error != 0) {
+ rseq_inactivate_sig(td, usig_addr, SEGV_RSEQ_R);
+ return (true);
+ }
+ if (usig != td->td_rseq_sig) {
+ rseq_inactivate_sig(td, usig_addr, SEGV_RSEQ_SIG);
+ return (true);
+ }
+ return (false);
+}
+
+static void
+ast_rseq(struct thread *td, int tda __unused)
+{
+ struct rseq rs;
+ struct rseq_cs rc;
+ register_t pc;
+ int cpu, error;
+ bool clear_cs;
+
+ if (td->td_rseq_abi == NULL)
+ return;
+
+ /*
+ * We cannot enter critical section there to keep td_oncpu
+ * valid due to userspace access. We do not even want to
+ * sched_pin() for the same reason.
+ *
+ * It is fine to get a context switch after reading td_oncpu,
+ * since this would cause new AST pending and we re-enter this
+ * function to update rseq cpu number.
+ *
+ * Microoptimize 64bit architectures by doing single 64bit
+ * write for cpu ids. For instance, on SMAP-enabled amd64
+ * this saves two serialization instructions STAC/CLAC.
+ */
+ cpu = td->td_oncpu;
+#ifdef __LP64__
+ rs.cpu_id_start = cpu;
+ rs.cpu_id = cpu;
+ error = suword64((char *)td->td_rseq_abi + offsetof(struct rseq,
+ cpu_id_start), *(uint64_t *)(char *)&rs.cpu_id_start);
+#else
+ error = suword((char *)td->td_rseq_abi + offsetof(struct rseq,
+ cpu_id_start), cpu);
+ if (error == 0) {
+ error = suword((char *)td->td_rseq_abi +
+ offsetof(struct rseq, cpu_id), cpu);
+ }
+#endif
+ if (error != 0) {
+ rseq_inactivate_sig(td, td->td_rseq_abi, SEGV_RSEQ_W);
+ return;
+ }
+
+ error = copyin(td->td_rseq_abi, &rs, sizeof(rs));
+ if (error != 0) {
+ rseq_inactivate_sig(td, td->td_rseq_abi, SEGV_RSEQ_R);
+ return;
+ }
+
+ if (rs.rseq_cs.ptr64 == 0)
+ return;
+ clear_cs = false;
+
+ critical_enter();
+ if ((td->td_flags & (TDF_RSEQ_CLRCS | TDF_RSEQ_MB)) == 0 &&
+ (rs.flags & RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT) != 0 &&
+ ((rs.flags & RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE) != 0 ||
+ td->td_oncpu == td->td_lastcpu))
+ return;
+ critical_exit();
+
+ error = copyin((void *)rs.rseq_cs.ptr64, &rc, sizeof(rc));
+ if (error != 0) {
+ rseq_inactivate_sig(td, (void *)rs.rseq_cs.ptr64, SEGV_RSEQ_R);
+ return;
+ }
+ if (rc.version != 0) {
+ rseq_inactivate_sig(td, (void *)rs.rseq_cs.ptr64, SEGV_RSEQ_R);
+ return;
+ }
+
+ critical_enter();
+ if ((td->td_flags & (TDF_RSEQ_CLRCS | TDF_RSEQ_MB)) == 0 &&
+ (rc.flags & RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT) != 0 &&
+ ((rc.flags & RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE) != 0 ||
+ td->td_oncpu == td->td_lastcpu))
+ return;
+ critical_exit();
+
+ if ((td->td_flags & (TDF_RSEQ_CLRCS | TDF_RSEQ_MB)) != 0) {
+ if ((td->td_flags & TDF_RSEQ_CLRCS) != 0)
+ clear_cs = true;
+ thread_lock(td);
+ td->td_flags &= ~(TDF_RSEQ_CLRCS | TDF_RSEQ_MB);
+ thread_unlock(td);
+ }
+ pc = TRAPF_PC(td->td_frame);
+ if (!clear_cs &&
+ pc >= rc.start_ip && pc < rc.start_ip + rc.post_commit_offset) {
+ if (rseq_check_signature(td, &rc))
+ return;
+
+ TRAPF_PC(td->td_frame) = rc.abort_ip;
+ clear_cs = true;
+ }
+ if (clear_cs) {
+ if (suword64((char *)td->td_rseq_abi + offsetof(struct rseq,
+ rseq_cs.ptr), 0) == -1) {
+ rseq_inactivate_sig(td, (char *)td->td_rseq_abi +
+ offsetof(struct rseq, rseq_cs.ptr),
+ SEGV_RSEQ_W);
+ return;
+ }
+ }
+}
+
+void
+rseq_before_sig(struct thread *td)
+{
+ struct rseq rs;
+ struct rseq_cs rc;
+ int error;
+
+ td->td_pflags2 &= ~TDP2_RSEQ_SIG;
+ if (td->td_rseq_abi == NULL)
+ return;
+
+ error = copyin(td->td_rseq_abi, &rs, sizeof(rs));
+ if (error != 0) {
+ rseq_inactivate_sig(td, td->td_rseq_abi, SEGV_RSEQ_R);
+ return;
+ }
+
+ if (rs.rseq_cs.ptr64 == 0 ||
+ (rs.flags & RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL) != 0)
+ return;
+
+ error = copyin((void *)rs.rseq_cs.ptr64, &rc, sizeof(rc));
+ if (error != 0) {
+ rseq_inactivate_sig(td, (void *)rs.rseq_cs.ptr64, SEGV_RSEQ_R);
+ return;
+ }
+
+ if ((rc.flags & RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL) != 0)
+ return;
+
+ if (rseq_check_signature(td, &rc))
+ return;
+
+ td->td_pflags2 |= TDP2_RSEQ_SIG;
+ td->td_rseq_start_ip = rc.start_ip;
+ td->td_rseq_end_ip = rc.start_ip + rc.post_commit_offset;
+ td->td_rseq_abort_ip = rc.abort_ip;
+}
+
+void
+rseq_on_sig(struct thread *td)
+{
+ register_t pc;
+
+ if ((td->td_pflags2 & TDP2_RSEQ_SIG) == 0)
+ return;
+ td->td_pflags2 &= ~TDP2_RSEQ_SIG;
+ pc = TRAPF_PC(td->td_frame);
+ if (pc >= td->td_rseq_start_ip && pc < td->td_rseq_end_ip) {
+ TRAPF_PC(td->td_frame) = td->td_rseq_abort_ip;
+ thread_lock(td);
+ ast_sched_locked(td, TDA_RSEQ);
+ td->td_flags |= TDF_RSEQ_CLRCS;
+ thread_unlock(td);
+ }
+}
+
+static int
+kern_rseq(struct thread *td, uintptr_t rseq, uint32_t rseqlen, int flags,
+ uint32_t sig)
+{
+ if (rseqlen != sizeof(struct rseq))
+ return (EINVAL);
+
+ if (flags == RSEQ_FLAG_UNREGISTER) {
+ if (rseq != 0 || td->td_rseq_abi == NULL)
+ return (EINVAL);
+ if (sig != td->td_rseq_sig)
+ return (EPERM);
+ rseq_inactivate(td);
+ return (0);
+ }
+
+ if (td->td_rseq_abi != NULL)
+ return (EBUSY);
+ if (flags != 0 || rseq == 0 ||
+ trunc_page(rseq) != trunc_page(rseq + rseqlen))
+ return (EINVAL);
+
+ td->td_rseq_abi = (void *)rseq;
+ td->td_rseq_sig = sig;
+ ast_sched(td, TDA_RSEQ);
+ return (0);
+}
+
+int
+sys_rseq(struct thread *td, struct rseq_args *uap)
+{
+ return (kern_rseq(td, (uintptr_t)uap->rseq, uap->rseqlen,
+ uap->flags, uap->sig));
+}
+
+static void
+rseq_init(void *arg __unused)
+{
+ ast_register(TDA_RSEQ, ASTR_ASTF_REQUIRED, 0, ast_rseq);
+}
+SYSINIT(rseq, SI_SUB_P1003_1B, SI_ORDER_ANY, rseq_init, NULL);
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -67,6 +67,7 @@
#include <sys/posix4.h>
#include <sys/racct.h>
#include <sys/resourcevar.h>
+#include <sys/rseq.h>
#include <sys/sdt.h>
#include <sys/sbuf.h>
#include <sys/sleepqueue.h>
@@ -2135,6 +2136,7 @@
KASSERT(_SIG_VALID(sig), ("invalid signal"));
sigfastblock_fetch(td);
+ rseq_before_sig(td);
PROC_LOCK(p);
ps = p->p_sigacts;
mtx_lock(&ps->ps_mtx);
@@ -2148,6 +2150,7 @@
ktrpsig(sig, ps->ps_sigact[_SIG_IDX(sig)],
&td->td_sigmask, ksi->ksi_code);
#endif
+ rseq_on_sig(td);
(*p->p_sysent->sv_sendsig)(ps->ps_sigact[_SIG_IDX(sig)],
ksi, &td->td_sigmask);
postsig_done(sig, td, ps);
@@ -3500,6 +3503,7 @@
if (p->p_sig == sig) {
p->p_sig = 0;
}
+ rseq_on_sig(td);
(*p->p_sysent->sv_sendsig)(action, &ksi, &returnmask);
postsig_done(sig, td, ps);
}
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c
--- a/sys/kern/kern_synch.c
+++ b/sys/kern/kern_synch.c
@@ -50,6 +50,7 @@
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/resourcevar.h>
+#include <sys/rseq.h>
#include <sys/sched.h>
#include <sys/sdt.h>
#include <sys/signalvar.h>
@@ -467,7 +468,7 @@
mi_switch(int flags)
{
uint64_t runtime, new_switchtime;
- struct thread *td;
+ struct thread *td, *td1;
td = curthread; /* XXX */
THREAD_LOCK_ASSERT(td, MA_OWNED | MA_NOTRECURSED);
@@ -530,10 +531,12 @@
/*
* If the last thread was exiting, finish cleaning it up.
*/
- if ((td = PCPU_GET(deadthread))) {
+ if ((td1 = PCPU_GET(deadthread))) {
PCPU_SET(deadthread, NULL);
- thread_stash(td);
+ thread_stash(td1);
}
+ if (td->td_rseq_abi != NULL)
+ ast_sched(td, TDA_RSEQ);
spinlock_exit();
}
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c
--- a/sys/kern/kern_thread.c
+++ b/sys/kern/kern_thread.c
@@ -90,9 +90,9 @@
"struct thread KBI td_flags");
_Static_assert(offsetof(struct thread, td_pflags) == 0x114,
"struct thread KBI td_pflags");
-_Static_assert(offsetof(struct thread, td_frame) == 0x4e8,
+_Static_assert(offsetof(struct thread, td_frame) == 0x510,
"struct thread KBI td_frame");
-_Static_assert(offsetof(struct thread, td_emuldata) == 0x6f0,
+_Static_assert(offsetof(struct thread, td_emuldata) == 0x720,
"struct thread KBI td_emuldata");
_Static_assert(offsetof(struct proc, p_flag) == 0xb8,
"struct proc KBI p_flag");
diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
--- a/sys/kern/subr_trap.c
+++ b/sys/kern/subr_trap.c
@@ -53,6 +53,7 @@
#include <sys/proc.h>
#include <sys/ktr.h>
#include <sys/resourcevar.h>
+#include <sys/rseq.h>
#include <sys/sched.h>
#include <sys/syscall.h>
#include <sys/syscallsubr.h>
diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c
--- a/sys/kern/syscalls.c
+++ b/sys/kern/syscalls.c
@@ -608,4 +608,5 @@
"pdrfork", /* 600 = pdrfork */
"pdwait", /* 601 = pdwait */
"renameat2", /* 602 = renameat2 */
+ "rseq", /* 603 = rseq */
};
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -3429,4 +3429,12 @@
int flags
);
}
+603 AUE_NULL STD|CAPENABLED {
+ int rseq(
+ _Inout_updates_bytes_(rseqlen) void *rseq,
+ uint32_t rseqlen,
+ int flags,
+ uint32_t sig
+ );
+ }
; vim: syntax=off
diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c
--- a/sys/kern/systrace_args.c
+++ b/sys/kern/systrace_args.c
@@ -3555,6 +3555,16 @@
*n_args = 5;
break;
}
+ /* rseq */
+ case 603: {
+ struct rseq_args *p = params;
+ uarg[a++] = (intptr_t)p->rseq; /* void * */
+ uarg[a++] = p->rseqlen; /* uint32_t */
+ iarg[a++] = p->flags; /* int */
+ uarg[a++] = p->sig; /* uint32_t */
+ *n_args = 4;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -9521,6 +9531,25 @@
break;
};
break;
+ /* rseq */
+ case 603:
+ switch (ndx) {
+ case 0:
+ p = "userland void *";
+ break;
+ case 1:
+ p = "uint32_t";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -11549,6 +11578,11 @@
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* rseq */
+ case 603:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h
--- a/sys/sys/elf_common.h
+++ b/sys/sys/elf_common.h
@@ -1721,5 +1721,6 @@
#define ELF_BSDF_SIGFASTBLK 0x0001 /* Kernel supports fast sigblock */
#define ELF_BSDF_VMNOOVERCOMMIT 0x0002
+#define ELF_BSDF_RSEQ1 0x0004 /* Kernel support for rseq v1 */
#endif /* !_SYS_ELF_COMMON_H_ */
diff --git a/sys/sys/membarrier.h b/sys/sys/membarrier.h
--- a/sys/sys/membarrier.h
+++ b/sys/sys/membarrier.h
@@ -47,12 +47,6 @@
MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED = 0x00000010,
MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE = 0x00000020,
MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE = 0x00000040,
-
- /*
- * RSEQ constants are defined for source compatibility but are
- * not yet supported, MEMBARRIER_CMD_QUERY does not return
- * them in the mask.
- */
MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ = 0x00000080,
MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ = 0x00000100,
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -323,6 +323,11 @@
struct kcov_info *td_kcov_info; /* (*) Kernel code coverage data */
long td_ucredref; /* (k) references on td_realucred */
struct kexterr td_kexterr;
+ uint32_t td_rseq_sig; /* (k) abort handler signature */
+ void *td_rseq_abi; /* (k) usermode rseq */
+ register_t td_rseq_start_ip;/* (k) */
+ register_t td_rseq_end_ip; /* (k) */
+ register_t td_rseq_abort_ip;/* (k) */
#define td_endzero td_sigmask
/* Copied during fork1(), thread_create(), or kthread_add(). */
@@ -477,9 +482,9 @@
#define TDF_SCHED2 0x04000000 /* Reserved for scheduler private use */
#define TDF_SCHED3 0x08000000 /* Reserved for scheduler private use */
#define TDF_UNUSED7 0x10000000 /* Available */
-#define TDF_UNUSED8 0x20000000 /* Available */
-#define TDF_UNUSED9 0x40000000 /* Available */
-#define TDF_UNUSED10 0x80000000 /* Available */
+#define TDF_RSEQ 0x20000000 /* rseq active */
+#define TDF_RSEQ_MB 0x40000000 /* MEMBARRIER_RSEQ requested */
+#define TDF_RSEQ_CLRCS 0x80000000 /* rseq clear rc */
enum {
TDA_AST = 0, /* Special: call all non-flagged AST handlers */
@@ -498,6 +503,7 @@
TDA_MOD2, /* processed .. */
TDA_PSELECT, /* For discarding temporary signal mask */
TDA_SIG,
+ TDA_RSEQ,
TDA_KTRACE,
TDA_SUSPEND,
TDA_SIGSUSPEND,
@@ -574,6 +580,7 @@
#define TDP2_SAN_QUIET 0x00000008 /* Disable warnings from K(A|M)SAN */
#define TDP2_EXTERR 0x00000010 /* Kernel reported ext error */
#define TDP2_UEXTERR 0x00000020 /* User set ext error reporting ptr */
+#define TDP2_RSEQ_SIG 0x00000040
/*
* Reasons that the current thread can not be run yet.
@@ -889,6 +896,8 @@
sync core registered */
#define P2_MEMBAR_GLOBE 0x00400000 /* membar global expedited
registered */
+#define P2_MEMBAR_PRIVE_RSEQ 0x00200000 /* membar private expedited
+ rseq registered */
#define P2_LOGSIGEXIT_ENABLE 0x00800000 /* Disable logging on sigexit */
#define P2_LOGSIGEXIT_CTL 0x01000000 /* Override kern.logsigexit */
diff --git a/sys/sys/rseq.h b/sys/sys/rseq.h
new file mode 100644
--- /dev/null
+++ b/sys/sys/rseq.h
@@ -0,0 +1,99 @@
+/*-
+ * Copyright (c) 2021 The FreeBSD Foundation
+ *
+ * This software were developed by Konstantin Belousov <kib@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __SYS_RSEQ_H__
+#define __SYS_RSEQ_H__
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/endian.h>
+
+enum rseq_cpu_id_state {
+ RSEQ_CPU_ID_UNINITIALIZED = -1,
+ RSEQ_CPU_ID_REGISTRATION_FAILED = -2,
+};
+
+enum rseq_flags {
+ RSEQ_FLAG_UNREGISTER = 1,
+};
+
+enum rseq_cs_flags {
+ RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT = 0x00000001,
+ RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL = 0x00000002,
+ RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE = 0x00000004,
+};
+
+struct rseq_cs {
+ uint32_t version;
+ uint32_t flags;
+ uint64_t start_ip;
+ uint64_t post_commit_offset;
+ uint64_t abort_ip;
+};
+
+struct rseq {
+ uint32_t cpu_id_start;
+ uint32_t cpu_id;
+ union {
+ uint64_t ptr64;
+#ifdef __LP64__
+ uint64_t ptr;
+#else
+ struct {
+#if _BYTE_ORDER == _BIG_ENDIAN
+ uint32_t pad;
+ uint32_t ptr32;
+#else /* BYTE_ORDER */
+ uint32_t ptr32;
+ uint32_t pad;
+#endif /* BYTE_ORDER */
+ } ptr;
+#endif /* LP64 */
+ } rseq_cs;
+ uint32_t flags;
+};
+
+#ifdef _KERNEL
+
+#define TD_RSEQ_ACTIVE 0x00000001
+
+void rseq_ast(struct thread *td);
+void rseq_before_sig(struct thread *td);
+void rseq_on_sig(struct thread *td);
+
+#else /* _KERNEL */
+
+__BEGIN_DECLS
+extern __thread volatile struct rseq __rseq_abi __weak_symbol;
+
+int rseq(volatile struct rseq *rseq, uint32_t rseqlen, int flags, uint32_t sig);
+__END_DECLS
+
+#endif /* _KERNEL */
+
+#endif /* __SYS_RSEQ_H__ */
diff --git a/sys/sys/signal.h b/sys/sys/signal.h
--- a/sys/sys/signal.h
+++ b/sys/sys/signal.h
@@ -306,6 +306,9 @@
#define SEGV_MAPERR 1 /* Address not mapped to object. */
#define SEGV_ACCERR 2 /* Invalid permissions for mapped */
/* object. */
+#define SEGV_RSEQ_R 51 /* rseq access read fault */
+#define SEGV_RSEQ_W 52 /* rseq access write fault */
+#define SEGV_RSEQ_SIG 53 /* rseq signature check fault */
#define SEGV_PKUERR 100 /* x86: PKU violation */
#define SEGV_MTEAERR 200 /* arm64: Asynchronous Arm MTE error */
#define SEGV_MTESERR 201 /* arm64: Synchronous Arm MTE error */
diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h
--- a/sys/sys/syscall.h
+++ b/sys/sys/syscall.h
@@ -541,4 +541,5 @@
#define SYS_pdrfork 600
#define SYS_pdwait 601
#define SYS_renameat2 602
-#define SYS_MAXSYSCALL 603
+#define SYS_rseq 603
+#define SYS_MAXSYSCALL 604
diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk
--- a/sys/sys/syscall.mk
+++ b/sys/sys/syscall.mk
@@ -444,4 +444,5 @@
kexec_load.o \
pdrfork.o \
pdwait.o \
- renameat2.o
+ renameat2.o \
+ rseq.o
diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h
--- a/sys/sys/sysproto.h
+++ b/sys/sys/sysproto.h
@@ -1932,6 +1932,12 @@
char new_l_[PADL_(const char *)]; const char * new; char new_r_[PADR_(const char *)];
char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
};
+struct rseq_args {
+ char rseq_l_[PADL_(void *)]; void * rseq; char rseq_r_[PADR_(void *)];
+ char rseqlen_l_[PADL_(uint32_t)]; uint32_t rseqlen; char rseqlen_r_[PADR_(uint32_t)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+ char sig_l_[PADL_(uint32_t)]; uint32_t sig; char sig_r_[PADR_(uint32_t)];
+};
int sys__exit(struct thread *, struct _exit_args *);
int sys_fork(struct thread *, struct fork_args *);
int sys_read(struct thread *, struct read_args *);
@@ -2342,6 +2348,7 @@
int sys_pdrfork(struct thread *, struct pdrfork_args *);
int sys_pdwait(struct thread *, struct pdwait_args *);
int sys_renameat2(struct thread *, struct renameat2_args *);
+int sys_rseq(struct thread *, struct rseq_args *);
#ifdef COMPAT_43
@@ -3344,6 +3351,7 @@
#define SYS_AUE_pdrfork AUE_PDRFORK
#define SYS_AUE_pdwait AUE_PDWAIT
#define SYS_AUE_renameat2 AUE_RENAMEAT
+#define SYS_AUE_rseq AUE_NULL
#undef PAD_
#undef PADL_

File Metadata

Mime Type
text/plain
Expires
Fri, Aug 28, 2:20 AM (10 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37406102
Default Alt Text
D32505.diff (34 KB)

Event Timeline