Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/amd64/vm_machdep.c
Show First 20 Lines • Show All 371 Lines • ▼ Show 20 Lines | |||||
cpu_exec_vmspace_reuse(struct proc *p, vm_map_t map) | cpu_exec_vmspace_reuse(struct proc *p, vm_map_t map) | ||||
{ | { | ||||
return (((curproc->p_md.md_flags & P_MD_KPTI) != 0) == | return (((curproc->p_md.md_flags & P_MD_KPTI) != 0) == | ||||
(vm_map_pmap(map)->pm_ucr3 != PMAP_NO_CR3)); | (vm_map_pmap(map)->pm_ucr3 != PMAP_NO_CR3)); | ||||
} | } | ||||
static void | static void | ||||
cpu_procctl_kpti(struct proc *p, int com, int *val) | cpu_procctl_kpti_ctl(struct proc *p, int val) | ||||
{ | { | ||||
if (com == PROC_KPTI_CTL) { | if (pti && val == PROC_KPTI_CTL_ENABLE_ON_EXEC) | ||||
if (pti && *val == PROC_KPTI_CTL_ENABLE_ON_EXEC) | |||||
p->p_md.md_flags |= P_MD_KPTI; | p->p_md.md_flags |= P_MD_KPTI; | ||||
if (*val == PROC_KPTI_CTL_DISABLE_ON_EXEC) | if (val == PROC_KPTI_CTL_DISABLE_ON_EXEC) | ||||
p->p_md.md_flags &= ~P_MD_KPTI; | p->p_md.md_flags &= ~P_MD_KPTI; | ||||
} else /* PROC_KPTI_STATUS */ { | } | ||||
static void | |||||
cpu_procctl_kpti_status(struct proc *p, int *val) | |||||
{ | |||||
*val = (p->p_md.md_flags & P_MD_KPTI) != 0 ? | *val = (p->p_md.md_flags & P_MD_KPTI) != 0 ? | ||||
PROC_KPTI_CTL_ENABLE_ON_EXEC: | PROC_KPTI_CTL_ENABLE_ON_EXEC: | ||||
PROC_KPTI_CTL_DISABLE_ON_EXEC; | PROC_KPTI_CTL_DISABLE_ON_EXEC; | ||||
if (vmspace_pmap(p->p_vmspace)->pm_ucr3 != PMAP_NO_CR3) | if (vmspace_pmap(p->p_vmspace)->pm_ucr3 != PMAP_NO_CR3) | ||||
*val |= PROC_KPTI_STATUS_ACTIVE; | *val |= PROC_KPTI_STATUS_ACTIVE; | ||||
} | } | ||||
static int | |||||
cpu_procctl_la_ctl(struct proc *p, int val) | |||||
{ | |||||
int error; | |||||
error = 0; | |||||
switch (val) { | |||||
case PROC_LA_CTL_LA48_ON_EXEC: | |||||
p->p_md.md_flags |= P_MD_LA48; | |||||
p->p_md.md_flags &= ~P_MD_LA57; | |||||
break; | |||||
case PROC_LA_CTL_LA57_ON_EXEC: | |||||
if (la57) { | |||||
p->p_md.md_flags &= ~P_MD_LA48; | |||||
p->p_md.md_flags |= P_MD_LA57; | |||||
} else { | |||||
error = ENOTSUP; | |||||
} | } | ||||
break; | |||||
case PROC_LA_CTL_DEFAULT_ON_EXEC: | |||||
p->p_md.md_flags &= ~(P_MD_LA48 | P_MD_LA57); | |||||
break; | |||||
} | |||||
return (error); | |||||
} | |||||
static void | |||||
cpu_procctl_la_status(struct proc *p, int *val) | |||||
{ | |||||
int res; | |||||
if ((p->p_md.md_flags & P_MD_LA48) != 0) | |||||
res = PROC_LA_CTL_LA48_ON_EXEC; | |||||
else if ((p->p_md.md_flags & P_MD_LA57) != 0) | |||||
res = PROC_LA_CTL_LA57_ON_EXEC; | |||||
else | |||||
res = PROC_LA_CTL_DEFAULT_ON_EXEC; | |||||
if (p->p_sysent->sv_maxuser == VM_MAXUSER_ADDRESS_LA48) | |||||
res |= PROC_LA_STATUS_LA48; | |||||
else | |||||
res |= PROC_LA_STATUS_LA57; | |||||
*val = res; | |||||
} | |||||
int | int | ||||
cpu_procctl(struct thread *td, int idtype, id_t id, int com, void *data) | cpu_procctl(struct thread *td, int idtype, id_t id, int com, void *data) | ||||
{ | { | ||||
struct proc *p; | struct proc *p; | ||||
int error, val; | int error, val; | ||||
switch (com) { | switch (com) { | ||||
case PROC_KPTI_CTL: | case PROC_KPTI_CTL: | ||||
case PROC_KPTI_STATUS: | case PROC_KPTI_STATUS: | ||||
case PROC_LA_CTL: | |||||
case PROC_LA_STATUS: | |||||
if (idtype != P_PID) { | if (idtype != P_PID) { | ||||
error = EINVAL; | error = EINVAL; | ||||
break; | break; | ||||
} | } | ||||
if (com == PROC_KPTI_CTL) { | if (com == PROC_KPTI_CTL) { | ||||
/* sad but true and not a joke */ | /* sad but true and not a joke */ | ||||
error = priv_check(td, PRIV_IO); | error = priv_check(td, PRIV_IO); | ||||
if (error != 0) | if (error != 0) | ||||
break; | break; | ||||
} | |||||
if (com == PROC_KPTI_CTL || com == PROC_LA_CTL) { | |||||
error = copyin(data, &val, sizeof(val)); | error = copyin(data, &val, sizeof(val)); | ||||
if (error != 0) | if (error != 0) | ||||
break; | break; | ||||
if (val != PROC_KPTI_CTL_ENABLE_ON_EXEC && | } | ||||
if (com == PROC_KPTI_CTL && | |||||
val != PROC_KPTI_CTL_ENABLE_ON_EXEC && | |||||
val != PROC_KPTI_CTL_DISABLE_ON_EXEC) { | val != PROC_KPTI_CTL_DISABLE_ON_EXEC) { | ||||
error = EINVAL; | error = EINVAL; | ||||
break; | break; | ||||
} | } | ||||
if (com == PROC_LA_CTL && | |||||
val != PROC_LA_CTL_LA48_ON_EXEC && | |||||
val != PROC_LA_CTL_LA57_ON_EXEC && | |||||
val != PROC_LA_CTL_DEFAULT_ON_EXEC) { | |||||
error = EINVAL; | |||||
break; | |||||
} | } | ||||
error = pget(id, PGET_CANSEE | PGET_NOTWEXIT | PGET_NOTID, &p); | error = pget(id, PGET_CANSEE | PGET_NOTWEXIT | PGET_NOTID, &p); | ||||
if (error == 0) { | if (error != 0) | ||||
cpu_procctl_kpti(p, com, &val); | break; | ||||
switch (com) { | |||||
case PROC_KPTI_CTL: | |||||
cpu_procctl_kpti_ctl(p, val); | |||||
break; | |||||
case PROC_KPTI_STATUS: | |||||
cpu_procctl_kpti_status(p, &val); | |||||
break; | |||||
case PROC_LA_CTL: | |||||
error = cpu_procctl_la_ctl(p, val); | |||||
break; | |||||
case PROC_LA_STATUS: | |||||
cpu_procctl_la_status(p, &val); | |||||
break; | |||||
} | |||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
if (com == PROC_KPTI_STATUS) | if (com == PROC_KPTI_STATUS || com == PROC_LA_STATUS) | ||||
error = copyout(&val, data, sizeof(val)); | error = copyout(&val, data, sizeof(val)); | ||||
} | |||||
break; | break; | ||||
default: | default: | ||||
error = EINVAL; | error = EINVAL; | ||||
break; | break; | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 222 Lines • Show Last 20 Lines |