summaryrefslogtreecommitdiff
path: root/sys/amd64
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2019-03-23 11:47:13 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2019-03-23 11:47:13 +0000
commitb120f251b6d0b4dbaa214d062fd754c57045dad4 (patch)
tree600eb8d2caa5eaee3f993283d6654d5121df0e3e /sys/amd64
parent687b89ad186fc8194b3c1ba11664179f32c79891 (diff)
Notes
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/amd64/vm_machdep.c63
-rw-r--r--sys/amd64/include/procctl.h6
2 files changed, 69 insertions, 0 deletions
diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c
index d95b63be26c4..84631383106a 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>
@@ -378,6 +381,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_amd64_md_flags |= P_MD_KPTI;
+ if (*val == PROC_KPTI_CTL_DISABLE_ON_EXEC)
+ p->p_amd64_md_flags &= ~P_MD_KPTI;
+ } else /* PROC_KPTI_STATUS */ {
+ *val = (p->p_amd64_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>