aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/amd64/amd64/vm_machdep.c63
-rw-r--r--sys/amd64/include/procctl.h6
-rw-r--r--sys/arm/arm/vm_machdep.c7
-rw-r--r--sys/arm/include/procctl.h4
-rw-r--r--sys/arm64/arm64/vm_machdep.c8
-rw-r--r--sys/arm64/include/procctl.h4
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c4
-rw-r--r--sys/i386/i386/vm_machdep.c8
-rw-r--r--sys/i386/include/procctl.h6
-rw-r--r--sys/kern/kern_procctl.c4
-rw-r--r--sys/mips/include/procctl.h4
-rw-r--r--sys/mips/mips/vm_machdep.c8
-rw-r--r--sys/powerpc/include/procctl.h4
-rw-r--r--sys/powerpc/powerpc/vm_machdep.c7
-rw-r--r--sys/riscv/include/procctl.h4
-rw-r--r--sys/riscv/riscv/vm_machdep.c8
-rw-r--r--sys/sparc64/include/procctl.h4
-rw-r--r--sys/sparc64/sparc64/vm_machdep.c8
-rw-r--r--sys/sys/proc.h2
-rw-r--r--sys/sys/procctl.h4
-rw-r--r--sys/x86/include/procctl.h43
21 files changed, 210 insertions, 0 deletions
diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c
index 0cf9eecc6d45..8508b6860297 100644
--- a/sys/amd64/amd64/vm_machdep.c
+++ b/sys/amd64/amd64/vm_machdep.c
@@ -59,13 +59,16 @@ __FBSDID("$FreeBSD$");
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/pioctl.h>
+#include <sys/priv.h>
#include <sys/proc.h>
+#include <sys/procctl.h>
#include <sys/smp.h>
#include <sys/sysctl.h>
#include <sys/sysent.h>
#include <sys/unistd.h>
#include <sys/vnode.h>
#include <sys/vmmeter.h>
+#include <sys/wait.h>
#include <machine/cpu.h>
#include <machine/md_var.h>
@@ -377,6 +380,66 @@ cpu_exec_vmspace_reuse(struct proc *p, vm_map_t map)
(vm_map_pmap(map)->pm_ucr3 != PMAP_NO_CR3));
}
+static void
+cpu_procctl_kpti(struct proc *p, int com, int *val)
+{
+
+ if (com == PROC_KPTI_CTL) {
+ if (pti && *val == PROC_KPTI_CTL_ENABLE_ON_EXEC)
+ p->p_md.md_flags |= P_MD_KPTI;
+ if (*val == PROC_KPTI_CTL_DISABLE_ON_EXEC)
+ p->p_md.md_flags &= ~P_MD_KPTI;
+ } else /* PROC_KPTI_STATUS */ {
+ *val = (p->p_md.md_flags & P_MD_KPTI) != 0 ?
+ PROC_KPTI_CTL_ENABLE_ON_EXEC:
+ PROC_KPTI_CTL_DISABLE_ON_EXEC;
+ if (vmspace_pmap(p->p_vmspace)->pm_ucr3 != PMAP_NO_CR3)
+ *val |= PROC_KPTI_STATUS_ACTIVE;
+ }
+}
+
+int
+cpu_procctl(struct thread *td, int idtype, id_t id, int com, void *data)
+{
+ struct proc *p;
+ int error, val;
+
+ switch (com) {
+ case PROC_KPTI_CTL:
+ case PROC_KPTI_STATUS:
+ if (idtype != P_PID) {
+ error = EINVAL;
+ break;
+ }
+ if (com == PROC_KPTI_CTL) {
+ /* sad but true and not a joke */
+ error = priv_check(td, PRIV_IO);
+ if (error != 0)
+ break;
+ error = copyin(data, &val, sizeof(val));
+ if (error != 0)
+ break;
+ if (val != PROC_KPTI_CTL_ENABLE_ON_EXEC &&
+ val != PROC_KPTI_CTL_DISABLE_ON_EXEC) {
+ error = EINVAL;
+ break;
+ }
+ }
+ error = pget(id, PGET_CANSEE | PGET_NOTWEXIT | PGET_NOTID, &p);
+ if (error == 0) {
+ cpu_procctl_kpti(p, com, &val);
+ PROC_UNLOCK(p);
+ if (com == PROC_KPTI_STATUS)
+ error = copyout(&val, data, sizeof(val));
+ }
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ return (error);
+}
+
void
cpu_set_syscall_retval(struct thread *td, int error)
{
diff --git a/sys/amd64/include/procctl.h b/sys/amd64/include/procctl.h
new file mode 100644
index 000000000000..4a6bcc712046
--- /dev/null
+++ b/sys/amd64/include/procctl.h
@@ -0,0 +1,6 @@
+/*-
+ * This file is in the public domain.
+ */
+/* $FreeBSD$ */
+
+#include <x86/procctl.h>
diff --git a/sys/arm/arm/vm_machdep.c b/sys/arm/arm/vm_machdep.c
index a2b457c2a253..3c75f43e5a1c 100644
--- a/sys/arm/arm/vm_machdep.c
+++ b/sys/arm/arm/vm_machdep.c
@@ -352,3 +352,10 @@ cpu_exec_vmspace_reuse(struct proc *p __unused, vm_map_t map __unused)
return (true);
}
+int
+cpu_procctl(struct thread *td __unused, int idtype __unused, id_t id __unused,
+ int com __unused, void *data __unused)
+{
+
+ return (EINVAL);
+}
diff --git a/sys/arm/include/procctl.h b/sys/arm/include/procctl.h
new file mode 100644
index 000000000000..5221cfcd7be1
--- /dev/null
+++ b/sys/arm/include/procctl.h
@@ -0,0 +1,4 @@
+/*-
+ * This file is in the public domain.
+ */
+/* $FreeBSD$ */
diff --git a/sys/arm64/arm64/vm_machdep.c b/sys/arm64/arm64/vm_machdep.c
index 083061b25846..af9a9c87519f 100644
--- a/sys/arm64/arm64/vm_machdep.c
+++ b/sys/arm64/arm64/vm_machdep.c
@@ -286,6 +286,14 @@ cpu_exec_vmspace_reuse(struct proc *p __unused, vm_map_t map __unused)
return (true);
}
+int
+cpu_procctl(struct thread *td __unused, int idtype __unused, id_t id __unused,
+ int com __unused, void *data __unused)
+{
+
+ return (EINVAL);
+}
+
void
swi_vm(void *v)
{
diff --git a/sys/arm64/include/procctl.h b/sys/arm64/include/procctl.h
new file mode 100644
index 000000000000..5221cfcd7be1
--- /dev/null
+++ b/sys/arm64/include/procctl.h
@@ -0,0 +1,4 @@
+/*-
+ * This file is in the public domain.
+ */
+/* $FreeBSD$ */
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index 64e3b046ecf0..81cb49a26867 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -3327,6 +3327,10 @@ freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap)
} x32;
int error, error1, flags, signum;
+ if (uap->com >= PROC_PROCCTL_MD_MIN)
+ return (cpu_procctl(td, uap->idtype, PAIR32TO64(id_t, uap->id),
+ uap->com, PTRIN(uap->data)));
+
switch (uap->com) {
case PROC_ASLR_CTL:
case PROC_SPROTECT:
diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c
index acc5a439ab0c..ef4772cd4ee5 100644
--- a/sys/i386/i386/vm_machdep.c
+++ b/sys/i386/i386/vm_machdep.c
@@ -389,6 +389,14 @@ cpu_exec_vmspace_reuse(struct proc *p __unused, vm_map_t map __unused)
return (true);
}
+int
+cpu_procctl(struct thread *td __unused, int idtype __unused, id_t id __unused,
+ int com __unused, void *data __unused)
+{
+
+ return (EINVAL);
+}
+
void
cpu_set_syscall_retval(struct thread *td, int error)
{
diff --git a/sys/i386/include/procctl.h b/sys/i386/include/procctl.h
new file mode 100644
index 000000000000..4a6bcc712046
--- /dev/null
+++ b/sys/i386/include/procctl.h
@@ -0,0 +1,6 @@
+/*-
+ * This file is in the public domain.
+ */
+/* $FreeBSD$ */
+
+#include <x86/procctl.h>
diff --git a/sys/kern/kern_procctl.c b/sys/kern/kern_procctl.c
index b02094322996..4e9f200aea79 100644
--- a/sys/kern/kern_procctl.c
+++ b/sys/kern/kern_procctl.c
@@ -494,6 +494,10 @@ sys_procctl(struct thread *td, struct procctl_args *uap)
} x;
int error, error1, flags, signum;
+ if (uap->com >= PROC_PROCCTL_MD_MIN)
+ return (cpu_procctl(td, uap->idtype, uap->id,
+ uap->com, uap->data));
+
switch (uap->com) {
case PROC_ASLR_CTL:
case PROC_SPROTECT:
diff --git a/sys/mips/include/procctl.h b/sys/mips/include/procctl.h
new file mode 100644
index 000000000000..5221cfcd7be1
--- /dev/null
+++ b/sys/mips/include/procctl.h
@@ -0,0 +1,4 @@
+/*-
+ * This file is in the public domain.
+ */
+/* $FreeBSD$ */
diff --git a/sys/mips/mips/vm_machdep.c b/sys/mips/mips/vm_machdep.c
index a224f81c4a68..e686ffcbcebe 100644
--- a/sys/mips/mips/vm_machdep.c
+++ b/sys/mips/mips/vm_machdep.c
@@ -460,6 +460,14 @@ cpu_exec_vmspace_reuse(struct proc *p __unused, vm_map_t map __unused)
return (true);
}
+int
+cpu_procctl(struct thread *td __unused, int idtype __unused, id_t id __unused,
+ int com __unused, void *data __unused)
+{
+
+ return (EINVAL);
+}
+
/*
* Software interrupt handler for queued VM system processing.
*/
diff --git a/sys/powerpc/include/procctl.h b/sys/powerpc/include/procctl.h
new file mode 100644
index 000000000000..5221cfcd7be1
--- /dev/null
+++ b/sys/powerpc/include/procctl.h
@@ -0,0 +1,4 @@
+/*-
+ * This file is in the public domain.
+ */
+/* $FreeBSD$ */
diff --git a/sys/powerpc/powerpc/vm_machdep.c b/sys/powerpc/powerpc/vm_machdep.c
index 7649711cef0a..4aab71ec036c 100644
--- a/sys/powerpc/powerpc/vm_machdep.c
+++ b/sys/powerpc/powerpc/vm_machdep.c
@@ -256,3 +256,10 @@ cpu_exec_vmspace_reuse(struct proc *p __unused, vm_map_t map __unused)
return (true);
}
+int
+cpu_procctl(struct thread *td __unused, int idtype __unused, id_t id __unused,
+ int com __unused, void *data __unused)
+{
+
+ return (EINVAL);
+}
diff --git a/sys/riscv/include/procctl.h b/sys/riscv/include/procctl.h
new file mode 100644
index 000000000000..5221cfcd7be1
--- /dev/null
+++ b/sys/riscv/include/procctl.h
@@ -0,0 +1,4 @@
+/*-
+ * This file is in the public domain.
+ */
+/* $FreeBSD$ */
diff --git a/sys/riscv/riscv/vm_machdep.c b/sys/riscv/riscv/vm_machdep.c
index 39119a07f581..7bcd13abc47d 100644
--- a/sys/riscv/riscv/vm_machdep.c
+++ b/sys/riscv/riscv/vm_machdep.c
@@ -271,6 +271,14 @@ cpu_exec_vmspace_reuse(struct proc *p __unused, vm_map_t map __unused)
return (true);
}
+int
+cpu_procctl(struct thread *td __unused, int idtype __unused, id_t id __unused,
+ int com __unused, void *data __unused)
+{
+
+ return (EINVAL);
+}
+
void
swi_vm(void *v)
{
diff --git a/sys/sparc64/include/procctl.h b/sys/sparc64/include/procctl.h
new file mode 100644
index 000000000000..5221cfcd7be1
--- /dev/null
+++ b/sys/sparc64/include/procctl.h
@@ -0,0 +1,4 @@
+/*-
+ * This file is in the public domain.
+ */
+/* $FreeBSD$ */
diff --git a/sys/sparc64/sparc64/vm_machdep.c b/sys/sparc64/sparc64/vm_machdep.c
index a4a316e0bc86..c56555a0120b 100644
--- a/sys/sparc64/sparc64/vm_machdep.c
+++ b/sys/sparc64/sparc64/vm_machdep.c
@@ -381,6 +381,14 @@ cpu_exec_vmspace_reuse(struct proc *p __unused, vm_map_t map __unused)
}
int
+cpu_procctl(struct thread *td __unused, int idtype __unused, id_t id __unused,
+ int com __unused, void *data __unused)
+{
+
+ return (EINVAL);
+}
+
+int
is_physical_memory(vm_paddr_t addr)
{
struct ofw_mem_region *mr;
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 2d71a72e4d2c..53d5cc88d58f 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -1097,6 +1097,8 @@ bool cpu_exec_vmspace_reuse(struct proc *p, struct vm_map *map);
int cpu_fetch_syscall_args(struct thread *td);
void cpu_fork(struct thread *, struct proc *, struct thread *, int);
void cpu_fork_kthread_handler(struct thread *, void (*)(void *), void *);
+int cpu_procctl(struct thread *td, int idtype, id_t id, int com,
+ void *data);
void cpu_set_syscall_retval(struct thread *, int);
void cpu_set_upcall(struct thread *, void (*)(void *), void *,
stack_t *);
diff --git a/sys/sys/procctl.h b/sys/sys/procctl.h
index 1f519454e963..80679f5eb972 100644
--- a/sys/sys/procctl.h
+++ b/sys/sys/procctl.h
@@ -41,6 +41,10 @@
#include <sys/wait.h>
#endif
+/* MD PROCCTL verbs start at 0x10000000 */
+#define PROC_PROCCTL_MD_MIN 0x10000000
+#include <machine/procctl.h>
+
#define PROC_SPROTECT 1 /* set protected state */
#define PROC_REAP_ACQUIRE 2 /* reaping enable */
#define PROC_REAP_RELEASE 3 /* reaping disable */
diff --git a/sys/x86/include/procctl.h b/sys/x86/include/procctl.h
new file mode 100644
index 000000000000..8cb792189020
--- /dev/null
+++ b/sys/x86/include/procctl.h
@@ -0,0 +1,43 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2019 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Konstantin Belousov
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _X86_PROCCTL_H
+#define _X86_PROCCTL_H
+
+#define PROC_KPTI_CTL (PROC_PROCCTL_MD_MIN + 0)
+#define PROC_KPTI_STATUS (PROC_PROCCTL_MD_MIN + 1)
+
+#define PROC_KPTI_CTL_ENABLE_ON_EXEC 1
+#define PROC_KPTI_CTL_DISABLE_ON_EXEC 2
+#define PROC_KPTI_STATUS_ACTIVE 0x80000000
+
+#endif