Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_procctl.c
Show First 20 Lines • Show All 585 Lines • ▼ Show 20 Lines | stackgap_status(struct thread *td, struct proc *p, int *data) | ||||
*data = (p->p_flag2 & P2_STKGAP_DISABLE) != 0 ? PROC_STACKGAP_DISABLE : | *data = (p->p_flag2 & P2_STKGAP_DISABLE) != 0 ? PROC_STACKGAP_DISABLE : | ||||
PROC_STACKGAP_ENABLE; | PROC_STACKGAP_ENABLE; | ||||
*data |= (p->p_flag2 & P2_STKGAP_DISABLE_EXEC) != 0 ? | *data |= (p->p_flag2 & P2_STKGAP_DISABLE_EXEC) != 0 ? | ||||
PROC_STACKGAP_DISABLE_EXEC : PROC_STACKGAP_ENABLE_EXEC; | PROC_STACKGAP_DISABLE_EXEC : PROC_STACKGAP_ENABLE_EXEC; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | |||||
wxorx_ctl(struct thread *td, struct proc *p, int state) | |||||
{ | |||||
struct vmspace *vm; | |||||
vm_map_t map; | |||||
PROC_LOCK_ASSERT(p, MA_OWNED); | |||||
if ((p->p_flag & P_WEXIT) != 0) | |||||
return (ESRCH); | |||||
switch (state) { | |||||
case PROC_WXORX_DISABLE: | |||||
markj: I think you need a P_WEXIT check here as you have below. | |||||
p->p_flag2 |= P2_WXORX_DISABLE; | |||||
_PHOLD(p); | |||||
PROC_UNLOCK(p); | |||||
vm = vmspace_acquire_ref(p); | |||||
if (vm != NULL) { | |||||
map = &vm->vm_map; | |||||
vm_map_lock(map); | |||||
map->flags &= ~MAP_WXORX; | |||||
vm_map_unlock(map); | |||||
vmspace_free(vm); | |||||
} | |||||
PROC_LOCK(p); | |||||
_PRELE(p); | |||||
break; | |||||
case PROC_WXORX_ENABLE_ON_EXEC: | |||||
p->p_flag2 |= P2_WXORX_ENABLE_EXEC; | |||||
break; | |||||
default: | |||||
return (EINVAL); | |||||
} | |||||
return (0); | |||||
} | |||||
static int | |||||
wxorx_status(struct thread *td, struct proc *p, int *data) | |||||
{ | |||||
struct vmspace *vm; | |||||
int d; | |||||
PROC_LOCK_ASSERT(p, MA_OWNED); | |||||
if ((p->p_flag & P_WEXIT) != 0) | |||||
return (ESRCH); | |||||
d = 0; | |||||
if ((p->p_flag2 & P2_WXORX_DISABLE) != 0) | |||||
d |= PROC_WXORX_DISABLE; | |||||
if ((p->p_flag2 & P2_WXORX_ENABLE_EXEC) != 0) | |||||
Done Inline ActionsWhat's the point of unlocking the proc at all? markj: What's the point of unlocking the proc at all? | |||||
Done Inline Actionsvmspace_acquire_ref() potentially results in the call to vmspace_free()->vmspace_dofree()->VM locking (e.g. sleepable vm map lock take) kib: vmspace_acquire_ref() potentially results in the call to vmspace_free()->vmspace_dofree()->VM… | |||||
d |= PROC_WXORX_ENABLE_ON_EXEC; | |||||
_PHOLD(p); | |||||
PROC_UNLOCK(p); | |||||
vm = vmspace_acquire_ref(p); | |||||
if (vm != NULL) { | |||||
if ((vm->vm_map.flags & MAP_WXORX) != 0) | |||||
d |= PROC_WXORX_ENFORCE; | |||||
vmspace_free(vm); | |||||
} | |||||
PROC_LOCK(p); | |||||
_PRELE(p); | |||||
*data = d; | |||||
return (0); | |||||
} | |||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct procctl_args { | struct procctl_args { | ||||
idtype_t idtype; | idtype_t idtype; | ||||
id_t id; | id_t id; | ||||
int com; | int com; | ||||
void *data; | void *data; | ||||
}; | }; | ||||
#endif | #endif | ||||
Show All 16 Lines | sys_procctl(struct thread *td, struct procctl_args *uap) | ||||
switch (uap->com) { | switch (uap->com) { | ||||
case PROC_ASLR_CTL: | case PROC_ASLR_CTL: | ||||
case PROC_PROTMAX_CTL: | case PROC_PROTMAX_CTL: | ||||
case PROC_SPROTECT: | case PROC_SPROTECT: | ||||
case PROC_STACKGAP_CTL: | case PROC_STACKGAP_CTL: | ||||
case PROC_TRACE_CTL: | case PROC_TRACE_CTL: | ||||
case PROC_TRAPCAP_CTL: | case PROC_TRAPCAP_CTL: | ||||
case PROC_NO_NEW_PRIVS_CTL: | case PROC_NO_NEW_PRIVS_CTL: | ||||
case PROC_WXORX_CTL: | |||||
error = copyin(uap->data, &flags, sizeof(flags)); | error = copyin(uap->data, &flags, sizeof(flags)); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
data = &flags; | data = &flags; | ||||
break; | break; | ||||
case PROC_REAP_ACQUIRE: | case PROC_REAP_ACQUIRE: | ||||
case PROC_REAP_RELEASE: | case PROC_REAP_RELEASE: | ||||
if (uap->data != NULL) | if (uap->data != NULL) | ||||
Show All 16 Lines | case PROC_REAP_KILL: | ||||
data = &x.rk; | data = &x.rk; | ||||
break; | break; | ||||
case PROC_ASLR_STATUS: | case PROC_ASLR_STATUS: | ||||
case PROC_PROTMAX_STATUS: | case PROC_PROTMAX_STATUS: | ||||
case PROC_STACKGAP_STATUS: | case PROC_STACKGAP_STATUS: | ||||
case PROC_TRACE_STATUS: | case PROC_TRACE_STATUS: | ||||
case PROC_TRAPCAP_STATUS: | case PROC_TRAPCAP_STATUS: | ||||
case PROC_NO_NEW_PRIVS_STATUS: | case PROC_NO_NEW_PRIVS_STATUS: | ||||
case PROC_WXORX_STATUS: | |||||
data = &flags; | data = &flags; | ||||
break; | break; | ||||
case PROC_PDEATHSIG_CTL: | case PROC_PDEATHSIG_CTL: | ||||
error = copyin(uap->data, &signum, sizeof(signum)); | error = copyin(uap->data, &signum, sizeof(signum)); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
data = &signum; | data = &signum; | ||||
break; | break; | ||||
Show All 15 Lines | if (error == 0) | ||||
error = error1; | error = error1; | ||||
break; | break; | ||||
case PROC_ASLR_STATUS: | case PROC_ASLR_STATUS: | ||||
case PROC_PROTMAX_STATUS: | case PROC_PROTMAX_STATUS: | ||||
case PROC_STACKGAP_STATUS: | case PROC_STACKGAP_STATUS: | ||||
case PROC_TRACE_STATUS: | case PROC_TRACE_STATUS: | ||||
case PROC_TRAPCAP_STATUS: | case PROC_TRAPCAP_STATUS: | ||||
case PROC_NO_NEW_PRIVS_STATUS: | case PROC_NO_NEW_PRIVS_STATUS: | ||||
case PROC_WXORX_STATUS: | |||||
if (error == 0) | if (error == 0) | ||||
error = copyout(&flags, uap->data, sizeof(flags)); | error = copyout(&flags, uap->data, sizeof(flags)); | ||||
break; | break; | ||||
case PROC_PDEATHSIG_STATUS: | case PROC_PDEATHSIG_STATUS: | ||||
if (error == 0) | if (error == 0) | ||||
error = copyout(&signum, uap->data, sizeof(signum)); | error = copyout(&signum, uap->data, sizeof(signum)); | ||||
break; | break; | ||||
} | } | ||||
Show All 37 Lines | kern_procctl_single(struct thread *td, struct proc *p, int com, void *data) | ||||
case PROC_TRAPCAP_CTL: | case PROC_TRAPCAP_CTL: | ||||
return (trapcap_ctl(td, p, *(int *)data)); | return (trapcap_ctl(td, p, *(int *)data)); | ||||
case PROC_TRAPCAP_STATUS: | case PROC_TRAPCAP_STATUS: | ||||
return (trapcap_status(td, p, data)); | return (trapcap_status(td, p, data)); | ||||
case PROC_NO_NEW_PRIVS_CTL: | case PROC_NO_NEW_PRIVS_CTL: | ||||
return (no_new_privs_ctl(td, p, *(int *)data)); | return (no_new_privs_ctl(td, p, *(int *)data)); | ||||
case PROC_NO_NEW_PRIVS_STATUS: | case PROC_NO_NEW_PRIVS_STATUS: | ||||
return (no_new_privs_status(td, p, data)); | return (no_new_privs_status(td, p, data)); | ||||
case PROC_WXORX_CTL: | |||||
return (wxorx_ctl(td, p, *(int *)data)); | |||||
case PROC_WXORX_STATUS: | |||||
return (wxorx_status(td, p, data)); | |||||
default: | default: | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
} | } | ||||
int | int | ||||
kern_procctl(struct thread *td, idtype_t idtype, id_t id, int com, void *data) | kern_procctl(struct thread *td, idtype_t idtype, id_t id, int com, void *data) | ||||
{ | { | ||||
Show All 16 Lines | kern_procctl(struct thread *td, idtype_t idtype, id_t id, int com, void *data) | ||||
case PROC_STACKGAP_CTL: | case PROC_STACKGAP_CTL: | ||||
case PROC_STACKGAP_STATUS: | case PROC_STACKGAP_STATUS: | ||||
case PROC_TRACE_STATUS: | case PROC_TRACE_STATUS: | ||||
case PROC_TRAPCAP_STATUS: | case PROC_TRAPCAP_STATUS: | ||||
case PROC_PDEATHSIG_CTL: | case PROC_PDEATHSIG_CTL: | ||||
case PROC_PDEATHSIG_STATUS: | case PROC_PDEATHSIG_STATUS: | ||||
case PROC_NO_NEW_PRIVS_CTL: | case PROC_NO_NEW_PRIVS_CTL: | ||||
case PROC_NO_NEW_PRIVS_STATUS: | case PROC_NO_NEW_PRIVS_STATUS: | ||||
case PROC_WXORX_CTL: | |||||
case PROC_WXORX_STATUS: | |||||
if (idtype != P_PID) | if (idtype != P_PID) | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
switch (com) { | switch (com) { | ||||
case PROC_PDEATHSIG_CTL: | case PROC_PDEATHSIG_CTL: | ||||
signum = *(int *)data; | signum = *(int *)data; | ||||
p = td->td_proc; | p = td->td_proc; | ||||
Show All 34 Lines | kern_procctl(struct thread *td, idtype_t idtype, id_t id, int com, void *data) | ||||
case PROC_ASLR_STATUS: | case PROC_ASLR_STATUS: | ||||
case PROC_PROTMAX_CTL: | case PROC_PROTMAX_CTL: | ||||
case PROC_PROTMAX_STATUS: | case PROC_PROTMAX_STATUS: | ||||
case PROC_STACKGAP_CTL: | case PROC_STACKGAP_CTL: | ||||
case PROC_STACKGAP_STATUS: | case PROC_STACKGAP_STATUS: | ||||
case PROC_TRACE_STATUS: | case PROC_TRACE_STATUS: | ||||
case PROC_TRAPCAP_STATUS: | case PROC_TRAPCAP_STATUS: | ||||
case PROC_NO_NEW_PRIVS_STATUS: | case PROC_NO_NEW_PRIVS_STATUS: | ||||
case PROC_WXORX_CTL: | |||||
case PROC_WXORX_STATUS: | |||||
tree_locked = false; | tree_locked = false; | ||||
break; | break; | ||||
default: | default: | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
switch (idtype) { | switch (idtype) { | ||||
case P_PID: | case P_PID: | ||||
▲ Show 20 Lines • Show All 57 Lines • Show Last 20 Lines |
I think you need a P_WEXIT check here as you have below.