diff options
| author | Konstantin Belousov <kib@FreeBSD.org> | 2019-03-23 11:47:13 +0000 |
|---|---|---|
| committer | Konstantin Belousov <kib@FreeBSD.org> | 2019-03-23 11:47:13 +0000 |
| commit | b120f251b6d0b4dbaa214d062fd754c57045dad4 (patch) | |
| tree | 600eb8d2caa5eaee3f993283d6654d5121df0e3e /sys/amd64 | |
| parent | 687b89ad186fc8194b3c1ba11664179f32c79891 (diff) | |
Notes
Diffstat (limited to 'sys/amd64')
| -rw-r--r-- | sys/amd64/amd64/vm_machdep.c | 63 | ||||
| -rw-r--r-- | sys/amd64/include/procctl.h | 6 |
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> |
