Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F131845008
D32513.id97117.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
22 KB
Referenced Files
None
Subscribers
None
D32513.id97117.diff
View Options
diff --git a/lib/libc/sys/procctl.2 b/lib/libc/sys/procctl.2
--- a/lib/libc/sys/procctl.2
+++ b/lib/libc/sys/procctl.2
@@ -62,6 +62,8 @@
.It Dv P_PID
Control the process with the process ID
.Fa id .
+.Fa id
+zero is a shortcut for the calling process ID.
.It Dv P_PGID
Control processes belonging to the process group with the ID
.Fa id .
@@ -70,6 +72,14 @@
The control request to perform is specified by the
.Fa cmd
argument.
+.Pp
+All status changing requests
+.Dv *_CTL
+require the caller to have the right to debug the target.
+All status query requests
+.DV *_STATUS
+require the caller to have the right to observe the target.
+.Pp
The following commands are supported:
.Bl -tag -width PROC_TRAPCAP_STATUS
.It Dv PROC_ASLR_CTL
diff --git a/sys/kern/kern_procctl.c b/sys/kern/kern_procctl.c
--- a/sys/kern/kern_procctl.c
+++ b/sys/kern/kern_procctl.c
@@ -102,10 +102,11 @@
}
static int
-protect_set(struct thread *td, struct proc *p, int flags)
+protect_set(struct thread *td, struct proc *p, void *data)
{
- int error, ret;
+ int error, flags, ret;
+ flags = *(int *)data;
switch (PPROT_OP(flags)) {
case PPROT_SET:
case PPROT_CLEAR:
@@ -131,11 +132,11 @@
}
static int
-reap_acquire(struct thread *td, struct proc *p)
+reap_acquire(struct thread *td, struct proc *p, void *data __unused)
{
sx_assert(&proctree_lock, SX_XLOCKED);
- if (p != curproc)
+ if (p != td->td_proc)
return (EPERM);
if ((p->p_treeflag & P_TREE_REAPER) != 0)
return (EBUSY);
@@ -148,11 +149,11 @@
}
static int
-reap_release(struct thread *td, struct proc *p)
+reap_release(struct thread *td, struct proc *p, void *data __unused)
{
sx_assert(&proctree_lock, SX_XLOCKED);
- if (p != curproc)
+ if (p != td->td_proc)
return (EPERM);
if (p == initproc)
return (EINVAL);
@@ -163,13 +164,13 @@
}
static int
-reap_status(struct thread *td, struct proc *p,
- struct procctl_reaper_status *rs)
+reap_status(struct thread *td, struct proc *p, void *data)
{
struct proc *reap, *p2, *first_p;
+ struct procctl_reaper_status *rs;
+ rs = data;
sx_assert(&proctree_lock, SX_LOCKED);
- bzero(rs, sizeof(*rs));
if ((p->p_treeflag & P_TREE_REAPER) == 0) {
reap = p->p_reaper;
} else {
@@ -198,13 +199,15 @@
}
static int
-reap_getpids(struct thread *td, struct proc *p, struct procctl_reaper_pids *rp)
+reap_getpids(struct thread *td, struct proc *p, void *data)
{
struct proc *reap, *p2;
struct procctl_reaper_pidinfo *pi, *pip;
+ struct procctl_reaper_pids *rp;
u_int i, n;
int error;
+ rp = data;
sx_assert(&proctree_lock, SX_LOCKED);
PROC_UNLOCK(p);
reap = (p->p_treeflag & P_TREE_REAPER) == 0 ? p->p_reaper : p;
@@ -276,14 +279,16 @@
}
static int
-reap_kill(struct thread *td, struct proc *p, struct procctl_reaper_kill *rk)
+reap_kill(struct thread *td, struct proc *p, void *data)
{
struct proc *reap, *p2;
ksiginfo_t ksi;
struct reap_kill_tracker_head tracker;
struct reap_kill_tracker *t;
+ struct procctl_reaper_kill *rk;
int error;
+ rk = data;
sx_assert(&proctree_lock, SX_LOCKED);
if (IN_CAPABILITY_MODE(td))
return (ECAPMODE);
@@ -336,10 +341,12 @@
}
static int
-trace_ctl(struct thread *td, struct proc *p, int state)
+trace_ctl(struct thread *td, struct proc *p, void *data)
{
+ int state;
PROC_LOCK_ASSERT(p, MA_OWNED);
+ state = *(int *)data;
/*
* Ktrace changes p_traceflag from or to zero under the
@@ -376,26 +383,30 @@
}
static int
-trace_status(struct thread *td, struct proc *p, int *data)
+trace_status(struct thread *td, struct proc *p, void *data)
{
+ int *status;
+ status = data;
if ((p->p_flag2 & P2_NOTRACE) != 0) {
KASSERT((p->p_flag & P_TRACED) == 0,
("%d traced but tracing disabled", p->p_pid));
- *data = -1;
+ *status = -1;
} else if ((p->p_flag & P_TRACED) != 0) {
- *data = p->p_pptr->p_pid;
+ *status = p->p_pptr->p_pid;
} else {
- *data = 0;
+ *status = 0;
}
return (0);
}
static int
-trapcap_ctl(struct thread *td, struct proc *p, int state)
+trapcap_ctl(struct thread *td, struct proc *p, void *data)
{
+ int state;
PROC_LOCK_ASSERT(p, MA_OWNED);
+ state = *(int *)data;
switch (state) {
case PROC_TRAPCAP_CTL_ENABLE:
@@ -411,19 +422,23 @@
}
static int
-trapcap_status(struct thread *td, struct proc *p, int *data)
+trapcap_status(struct thread *td, struct proc *p, void *data)
{
+ int *status;
- *data = (p->p_flag2 & P2_TRAPCAP) != 0 ? PROC_TRAPCAP_CTL_ENABLE :
+ status = data;
+ *status = (p->p_flag2 & P2_TRAPCAP) != 0 ? PROC_TRAPCAP_CTL_ENABLE :
PROC_TRAPCAP_CTL_DISABLE;
return (0);
}
static int
-no_new_privs_ctl(struct thread *td, struct proc *p, int state)
+no_new_privs_ctl(struct thread *td, struct proc *p, void *data)
{
+ int state;
PROC_LOCK_ASSERT(p, MA_OWNED);
+ state = *(int *)data;
if (state != PROC_NO_NEW_PRIVS_ENABLE)
return (EINVAL);
@@ -432,18 +447,21 @@
}
static int
-no_new_privs_status(struct thread *td, struct proc *p, int *data)
+no_new_privs_status(struct thread *td, struct proc *p, void *data)
{
- *data = (p->p_flag2 & P2_NO_NEW_PRIVS) != 0 ?
+ *(int *)data = (p->p_flag2 & P2_NO_NEW_PRIVS) != 0 ?
PROC_NO_NEW_PRIVS_ENABLE : PROC_NO_NEW_PRIVS_DISABLE;
return (0);
}
static int
-protmax_ctl(struct thread *td, struct proc *p, int state)
+protmax_ctl(struct thread *td, struct proc *p, void *data)
{
+ int state;
+
PROC_LOCK_ASSERT(p, MA_OWNED);
+ state = *(int *)data;
switch (state) {
case PROC_PROTMAX_FORCE_ENABLE:
@@ -464,7 +482,7 @@
}
static int
-protmax_status(struct thread *td, struct proc *p, int *data)
+protmax_status(struct thread *td, struct proc *p, void *data)
{
int d;
@@ -481,15 +499,17 @@
}
if (kern_mmap_maxprot(p, PROT_READ) == PROT_READ)
d |= PROC_PROTMAX_ACTIVE;
- *data = d;
+ *(int *)data = d;
return (0);
}
static int
-aslr_ctl(struct thread *td, struct proc *p, int state)
+aslr_ctl(struct thread *td, struct proc *p, void *data)
{
+ int state;
PROC_LOCK_ASSERT(p, MA_OWNED);
+ state = *(int *)data;
switch (state) {
case PROC_ASLR_FORCE_ENABLE:
@@ -510,7 +530,7 @@
}
static int
-aslr_status(struct thread *td, struct proc *p, int *data)
+aslr_status(struct thread *td, struct proc *p, void *data)
{
struct vmspace *vm;
int d;
@@ -538,14 +558,17 @@
PROC_LOCK(p);
_PRELE(p);
}
- *data = d;
+ *(int *)data = d;
return (0);
}
static int
-stackgap_ctl(struct thread *td, struct proc *p, int state)
+stackgap_ctl(struct thread *td, struct proc *p, void *data)
{
+ int state;
+
PROC_LOCK_ASSERT(p, MA_OWNED);
+ state = *(int *)data;
if ((state & ~(PROC_STACKGAP_ENABLE | PROC_STACKGAP_DISABLE |
PROC_STACKGAP_ENABLE_EXEC | PROC_STACKGAP_DISABLE_EXEC)) != 0)
@@ -580,26 +603,31 @@
}
static int
-stackgap_status(struct thread *td, struct proc *p, int *data)
+stackgap_status(struct thread *td, struct proc *p, void *data)
{
+ int d;
+
PROC_LOCK_ASSERT(p, MA_OWNED);
- *data = (p->p_flag2 & P2_STKGAP_DISABLE) != 0 ? PROC_STACKGAP_DISABLE :
+ d = (p->p_flag2 & P2_STKGAP_DISABLE) != 0 ? PROC_STACKGAP_DISABLE :
PROC_STACKGAP_ENABLE;
- *data |= (p->p_flag2 & P2_STKGAP_DISABLE_EXEC) != 0 ?
+ d |= (p->p_flag2 & P2_STKGAP_DISABLE_EXEC) != 0 ?
PROC_STACKGAP_DISABLE_EXEC : PROC_STACKGAP_ENABLE_EXEC;
+ *(int *)data = d;
return (0);
}
static int
-wxmap_ctl(struct thread *td, struct proc *p, int state)
+wxmap_ctl(struct thread *td, struct proc *p, void *data)
{
struct vmspace *vm;
vm_map_t map;
+ int state;
PROC_LOCK_ASSERT(p, MA_OWNED);
if ((p->p_flag & P_WEXIT) != 0)
return (ESRCH);
+ state = *(int *)data;
switch (state) {
case PROC_WX_MAPPINGS_PERMIT:
@@ -628,7 +656,7 @@
}
static int
-wxmap_status(struct thread *td, struct proc *p, int *data)
+wxmap_status(struct thread *td, struct proc *p, void *data)
{
struct vmspace *vm;
int d;
@@ -652,115 +680,215 @@
}
PROC_LOCK(p);
_PRELE(p);
- *data = d;
+ *(int *)data = d;
+ return (0);
+}
+
+static int
+pdeathsig_ctl(struct thread *td, struct proc *p, void *data)
+{
+ int signum;
+
+ signum = *(int *)data;
+ if (p != td->td_proc || (signum != 0 && !_SIG_VALID(signum)))
+ return (EINVAL);
+ p->p_pdeathsig = signum;
+ return (0);
+}
+
+static int
+pdeathsig_status(struct thread *td, struct proc *p, void *data)
+{
+ if (p != td->td_proc)
+ return (EINVAL);
+ *(int *)data = p->p_pdeathsig;
return (0);
}
-#ifndef _SYS_SYSPROTO_H_
-struct procctl_args {
- idtype_t idtype;
- id_t id;
- int com;
- void *data;
+struct procctl_cmd_info {
+ int lock_tree;
+ bool one_proc : 1;
+ bool esrch_is_einval : 1;
+ bool copyout_on_error : 1;
+ bool no_nonnull_data : 1;
+ bool need_candebug : 1;
+ int copyin_sz;
+ int copyout_sz;
+ int (*exec)(struct thread *, struct proc *, void *);
};
-#endif
-/* ARGSUSED */
+static const struct procctl_cmd_info procctl_cmds_info[] = {
+ [PROC_SPROTECT] =
+ { .lock_tree = SA_SLOCKED, .one_proc = false,
+ .esrch_is_einval = false, .no_nonnull_data = false,
+ .need_candebug = false,
+ .copyin_sz = sizeof(int), .copyout_sz = 0,
+ .exec = protect_set, .copyout_on_error = false, },
+ [PROC_REAP_ACQUIRE] =
+ { .lock_tree = SA_XLOCKED, .one_proc = true,
+ .esrch_is_einval = false, .no_nonnull_data = true,
+ .need_candebug = false,
+ .copyin_sz = 0, .copyout_sz = 0,
+ .exec = reap_acquire, .copyout_on_error = false, },
+ [PROC_REAP_RELEASE] =
+ { .lock_tree = SA_XLOCKED, .one_proc = true,
+ .esrch_is_einval = false, .no_nonnull_data = true,
+ .need_candebug = false,
+ .copyin_sz = 0, .copyout_sz = 0,
+ .exec = reap_release, .copyout_on_error = false, },
+ [PROC_REAP_STATUS] =
+ { .lock_tree = SA_SLOCKED, .one_proc = true,
+ .esrch_is_einval = false, .no_nonnull_data = false,
+ .need_candebug = false,
+ .copyin_sz = 0,
+ .copyout_sz = sizeof(struct procctl_reaper_status),
+ .exec = reap_status, .copyout_on_error = false, },
+ [PROC_REAP_GETPIDS] =
+ { .lock_tree = SA_SLOCKED, .one_proc = true,
+ .esrch_is_einval = false, .no_nonnull_data = false,
+ .need_candebug = false,
+ .copyin_sz = sizeof(struct procctl_reaper_pids),
+ .copyout_sz = 0,
+ .exec = reap_getpids, .copyout_on_error = false, },
+ [PROC_REAP_KILL] =
+ { .lock_tree = SA_SLOCKED, .one_proc = true,
+ .esrch_is_einval = false, .no_nonnull_data = false,
+ .need_candebug = false,
+ .copyin_sz = sizeof(struct procctl_reaper_kill),
+ .copyout_sz = sizeof(struct procctl_reaper_kill),
+ .exec = reap_kill, .copyout_on_error = true, },
+ [PROC_TRACE_CTL] =
+ { .lock_tree = SA_SLOCKED, .one_proc = false,
+ .esrch_is_einval = false, .no_nonnull_data = false,
+ .need_candebug = true,
+ .copyin_sz = sizeof(int), .copyout_sz = 0,
+ .exec = trace_ctl, .copyout_on_error = false, },
+ [PROC_TRACE_STATUS] =
+ { .lock_tree = SA_UNLOCKED, .one_proc = true,
+ .esrch_is_einval = false, .no_nonnull_data = false,
+ .need_candebug = false,
+ .copyin_sz = 0, .copyout_sz = sizeof(int),
+ .exec = trace_status, .copyout_on_error = false, },
+ [PROC_TRAPCAP_CTL] =
+ { .lock_tree = SA_SLOCKED, .one_proc = false,
+ .esrch_is_einval = false, .no_nonnull_data = false,
+ .need_candebug = true,
+ .copyin_sz = sizeof(int), .copyout_sz = 0,
+ .exec = trapcap_ctl, .copyout_on_error = false, },
+ [PROC_TRAPCAP_STATUS] =
+ { .lock_tree = SA_UNLOCKED, .one_proc = true,
+ .esrch_is_einval = false, .no_nonnull_data = false,
+ .need_candebug = false,
+ .copyin_sz = 0, .copyout_sz = sizeof(int),
+ .exec = trapcap_status, .copyout_on_error = false, },
+ [PROC_PDEATHSIG_CTL] =
+ { .lock_tree = SA_UNLOCKED, .one_proc = true,
+ .esrch_is_einval = true, .no_nonnull_data = false,
+ .need_candebug = false,
+ .copyin_sz = sizeof(int), .copyout_sz = 0,
+ .exec = pdeathsig_ctl, .copyout_on_error = false, },
+ [PROC_PDEATHSIG_STATUS] =
+ { .lock_tree = SA_UNLOCKED, .one_proc = true,
+ .esrch_is_einval = true, .no_nonnull_data = false,
+ .need_candebug = false,
+ .copyin_sz = 0, .copyout_sz = sizeof(int),
+ .exec = pdeathsig_status, .copyout_on_error = false, },
+ [PROC_ASLR_CTL] =
+ { .lock_tree = SA_UNLOCKED, .one_proc = true,
+ .esrch_is_einval = false, .no_nonnull_data = false,
+ .need_candebug = true,
+ .copyin_sz = sizeof(int), .copyout_sz = 0,
+ .exec = aslr_ctl, .copyout_on_error = false, },
+ [PROC_ASLR_STATUS] =
+ { .lock_tree = SA_UNLOCKED, .one_proc = true,
+ .esrch_is_einval = false, .no_nonnull_data = false,
+ .need_candebug = false,
+ .copyin_sz = 0, .copyout_sz = sizeof(int),
+ .exec = aslr_status, .copyout_on_error = false, },
+ [PROC_PROTMAX_CTL] =
+ { .lock_tree = SA_UNLOCKED, .one_proc = true,
+ .esrch_is_einval = false, .no_nonnull_data = false,
+ .need_candebug = true,
+ .copyin_sz = sizeof(int), .copyout_sz = 0,
+ .exec = protmax_ctl, .copyout_on_error = false, },
+ [PROC_PROTMAX_STATUS] =
+ { .lock_tree = SA_UNLOCKED, .one_proc = true,
+ .esrch_is_einval = false, .no_nonnull_data = false,
+ .need_candebug = false,
+ .copyin_sz = 0, .copyout_sz = sizeof(int),
+ .exec = protmax_status, .copyout_on_error = false, },
+ [PROC_STACKGAP_CTL] =
+ { .lock_tree = SA_UNLOCKED, .one_proc = true,
+ .esrch_is_einval = false, .no_nonnull_data = false,
+ .need_candebug = true,
+ .copyin_sz = sizeof(int), .copyout_sz = 0,
+ .exec = stackgap_ctl, .copyout_on_error = false, },
+ [PROC_STACKGAP_STATUS] =
+ { .lock_tree = SA_UNLOCKED, .one_proc = true,
+ .esrch_is_einval = false, .no_nonnull_data = false,
+ .need_candebug = false,
+ .copyin_sz = 0, .copyout_sz = sizeof(int),
+ .exec = stackgap_status, .copyout_on_error = false, },
+ [PROC_NO_NEW_PRIVS_CTL] =
+ { .lock_tree = SA_SLOCKED, .one_proc = true,
+ .esrch_is_einval = false, .no_nonnull_data = false,
+ .need_candebug = true,
+ .copyin_sz = sizeof(int), .copyout_sz = 0,
+ .exec = no_new_privs_ctl, .copyout_on_error = false, },
+ [PROC_NO_NEW_PRIVS_STATUS] =
+ { .lock_tree = SA_UNLOCKED, .one_proc = true,
+ .esrch_is_einval = false, .no_nonnull_data = false,
+ .need_candebug = false,
+ .copyin_sz = 0, .copyout_sz = sizeof(int),
+ .exec = no_new_privs_status, .copyout_on_error = false, },
+ [PROC_WXMAP_CTL] =
+ { .lock_tree = SA_UNLOCKED, .one_proc = true,
+ .esrch_is_einval = false, .no_nonnull_data = false,
+ .need_candebug = true,
+ .copyin_sz = sizeof(int), .copyout_sz = 0,
+ .exec = wxmap_ctl, .copyout_on_error = false, },
+ [PROC_WXMAP_STATUS] =
+ { .lock_tree = SA_UNLOCKED, .one_proc = true,
+ .esrch_is_einval = false, .no_nonnull_data = false,
+ .need_candebug = false,
+ .copyin_sz = 0, .copyout_sz = sizeof(int),
+ .exec = wxmap_status, .copyout_on_error = false, },
+};
+
int
sys_procctl(struct thread *td, struct procctl_args *uap)
{
- void *data;
union {
struct procctl_reaper_status rs;
struct procctl_reaper_pids rp;
struct procctl_reaper_kill rk;
+ int flags;
} x;
- int error, error1, flags, signum;
+ const struct procctl_cmd_info *cmd_info;
+ int error, error1;
if (uap->com >= PROC_PROCCTL_MD_MIN)
return (cpu_procctl(td, uap->idtype, uap->id,
uap->com, uap->data));
+ if (uap->com == 0 || uap->com >= nitems(procctl_cmds_info))
+ return (EINVAL);
+ cmd_info = &procctl_cmds_info[uap->com];
+ bzero(&x, sizeof(x));
- switch (uap->com) {
- case PROC_ASLR_CTL:
- case PROC_PROTMAX_CTL:
- case PROC_SPROTECT:
- case PROC_STACKGAP_CTL:
- case PROC_TRACE_CTL:
- case PROC_TRAPCAP_CTL:
- case PROC_NO_NEW_PRIVS_CTL:
- case PROC_WXMAP_CTL:
- error = copyin(uap->data, &flags, sizeof(flags));
- if (error != 0)
- return (error);
- data = &flags;
- break;
- case PROC_REAP_ACQUIRE:
- case PROC_REAP_RELEASE:
- if (uap->data != NULL)
- return (EINVAL);
- data = NULL;
- break;
- case PROC_REAP_STATUS:
- data = &x.rs;
- break;
- case PROC_REAP_GETPIDS:
- error = copyin(uap->data, &x.rp, sizeof(x.rp));
- if (error != 0)
- return (error);
- data = &x.rp;
- break;
- case PROC_REAP_KILL:
- error = copyin(uap->data, &x.rk, sizeof(x.rk));
+ if (cmd_info->copyin_sz > 0) {
+ error = copyin(uap->data, &x, cmd_info->copyin_sz);
if (error != 0)
return (error);
- data = &x.rk;
- break;
- case PROC_ASLR_STATUS:
- case PROC_PROTMAX_STATUS:
- case PROC_STACKGAP_STATUS:
- case PROC_TRACE_STATUS:
- case PROC_TRAPCAP_STATUS:
- case PROC_NO_NEW_PRIVS_STATUS:
- case PROC_WXMAP_STATUS:
- data = &flags;
- break;
- case PROC_PDEATHSIG_CTL:
- error = copyin(uap->data, &signum, sizeof(signum));
- if (error != 0)
- return (error);
- data = &signum;
- break;
- case PROC_PDEATHSIG_STATUS:
- data = &signum;
- break;
- default:
+ } else if (cmd_info->no_nonnull_data && uap->data != NULL) {
return (EINVAL);
}
- error = kern_procctl(td, uap->idtype, uap->id, uap->com, data);
- switch (uap->com) {
- case PROC_REAP_STATUS:
- if (error == 0)
- error = copyout(&x.rs, uap->data, sizeof(x.rs));
- break;
- case PROC_REAP_KILL:
- error1 = copyout(&x.rk, uap->data, sizeof(x.rk));
+
+ error = kern_procctl(td, uap->idtype, uap->id, uap->com, &x);
+
+ if (cmd_info->copyout_sz > 0 && (error == 0 ||
+ cmd_info->copyout_on_error)) {
+ error1 = copyout(&x, uap->data, cmd_info->copyout_sz);
if (error == 0)
error = error1;
- break;
- case PROC_ASLR_STATUS:
- case PROC_PROTMAX_STATUS:
- case PROC_STACKGAP_STATUS:
- case PROC_TRACE_STATUS:
- case PROC_TRAPCAP_STATUS:
- case PROC_NO_NEW_PRIVS_STATUS:
- case PROC_WXMAP_STATUS:
- if (error == 0)
- error = copyout(&flags, uap->data, sizeof(flags));
- break;
- case PROC_PDEATHSIG_STATUS:
- if (error == 0)
- error = copyout(&signum, uap->data, sizeof(signum));
- break;
}
return (error);
}
@@ -770,50 +898,7 @@
{
PROC_LOCK_ASSERT(p, MA_OWNED);
- switch (com) {
- case PROC_ASLR_CTL:
- return (aslr_ctl(td, p, *(int *)data));
- case PROC_ASLR_STATUS:
- return (aslr_status(td, p, data));
- case PROC_SPROTECT:
- return (protect_set(td, p, *(int *)data));
- case PROC_PROTMAX_CTL:
- return (protmax_ctl(td, p, *(int *)data));
- case PROC_PROTMAX_STATUS:
- return (protmax_status(td, p, data));
- case PROC_STACKGAP_CTL:
- return (stackgap_ctl(td, p, *(int *)data));
- case PROC_STACKGAP_STATUS:
- return (stackgap_status(td, p, data));
- case PROC_REAP_ACQUIRE:
- return (reap_acquire(td, p));
- case PROC_REAP_RELEASE:
- return (reap_release(td, p));
- case PROC_REAP_STATUS:
- return (reap_status(td, p, data));
- case PROC_REAP_GETPIDS:
- return (reap_getpids(td, p, data));
- case PROC_REAP_KILL:
- return (reap_kill(td, p, data));
- case PROC_TRACE_CTL:
- return (trace_ctl(td, p, *(int *)data));
- case PROC_TRACE_STATUS:
- return (trace_status(td, p, data));
- case PROC_TRAPCAP_CTL:
- return (trapcap_ctl(td, p, *(int *)data));
- case PROC_TRAPCAP_STATUS:
- return (trapcap_status(td, p, data));
- case PROC_NO_NEW_PRIVS_CTL:
- return (no_new_privs_ctl(td, p, *(int *)data));
- case PROC_NO_NEW_PRIVS_STATUS:
- return (no_new_privs_status(td, p, data));
- case PROC_WXMAP_CTL:
- return (wxmap_ctl(td, p, *(int *)data));
- case PROC_WXMAP_STATUS:
- return (wxmap_status(td, p, data));
- default:
- return (EINVAL);
- }
+ return (procctl_cmds_info[com].exec(td, p, data));
}
int
@@ -821,96 +906,39 @@
{
struct pgrp *pg;
struct proc *p;
+ const struct procctl_cmd_info *cmd_info;
int error, first_error, ok;
- int signum;
- bool tree_locked;
-
- switch (com) {
- case PROC_ASLR_CTL:
- case PROC_ASLR_STATUS:
- case PROC_PROTMAX_CTL:
- case PROC_PROTMAX_STATUS:
- case PROC_REAP_ACQUIRE:
- case PROC_REAP_RELEASE:
- case PROC_REAP_STATUS:
- case PROC_REAP_GETPIDS:
- case PROC_REAP_KILL:
- case PROC_STACKGAP_CTL:
- case PROC_STACKGAP_STATUS:
- case PROC_TRACE_STATUS:
- case PROC_TRAPCAP_STATUS:
- case PROC_PDEATHSIG_CTL:
- case PROC_PDEATHSIG_STATUS:
- case PROC_NO_NEW_PRIVS_CTL:
- case PROC_NO_NEW_PRIVS_STATUS:
- case PROC_WXMAP_CTL:
- case PROC_WXMAP_STATUS:
- if (idtype != P_PID)
- return (EINVAL);
- }
- switch (com) {
- case PROC_PDEATHSIG_CTL:
- signum = *(int *)data;
- p = td->td_proc;
- if ((id != 0 && id != p->p_pid) ||
- (signum != 0 && !_SIG_VALID(signum)))
- return (EINVAL);
- PROC_LOCK(p);
- p->p_pdeathsig = signum;
- PROC_UNLOCK(p);
- return (0);
- case PROC_PDEATHSIG_STATUS:
- p = td->td_proc;
- if (id != 0 && id != p->p_pid)
- return (EINVAL);
- PROC_LOCK(p);
- *(int *)data = p->p_pdeathsig;
- PROC_UNLOCK(p);
- return (0);
- }
+ MPASS(com > 0 && com < nitems(procctl_cmds_info));
+ cmd_info = &procctl_cmds_info[com];
+ if (idtype != P_PID && cmd_info->one_proc)
+ return (EINVAL);
- switch (com) {
- case PROC_SPROTECT:
- case PROC_REAP_STATUS:
- case PROC_REAP_GETPIDS:
- case PROC_REAP_KILL:
- case PROC_TRACE_CTL:
- case PROC_TRAPCAP_CTL:
- case PROC_NO_NEW_PRIVS_CTL:
- sx_slock(&proctree_lock);
- tree_locked = true;
- break;
- case PROC_REAP_ACQUIRE:
- case PROC_REAP_RELEASE:
+ switch (cmd_info->lock_tree) {
+ case SA_XLOCKED:
sx_xlock(&proctree_lock);
- tree_locked = true;
- break;
- case PROC_ASLR_CTL:
- case PROC_ASLR_STATUS:
- case PROC_PROTMAX_CTL:
- case PROC_PROTMAX_STATUS:
- case PROC_STACKGAP_CTL:
- case PROC_STACKGAP_STATUS:
- case PROC_TRACE_STATUS:
- case PROC_TRAPCAP_STATUS:
- case PROC_NO_NEW_PRIVS_STATUS:
- case PROC_WXMAP_CTL:
- case PROC_WXMAP_STATUS:
- tree_locked = false;
break;
- default:
- return (EINVAL);
+ case SA_SLOCKED:
+ sx_slock(&proctree_lock);
+ break;
}
switch (idtype) {
case P_PID:
- p = pfind(id);
- if (p == NULL) {
- error = ESRCH;
- break;
+ if (id == 0) {
+ p = td->td_proc;
+ error = 0;
+ PROC_LOCK(p);
+ } else {
+ p = pfind(id);
+ if (p == NULL) {
+ error = cmd_info->esrch_is_einval ?
+ EINVAL : ESRCH;
+ break;
+ }
+ error = cmd_info->need_candebug ? p_candebug(td, p) :
+ p_cansee(td, p);
}
- error = p_cansee(td, p);
if (error == 0)
error = kern_procctl_single(td, p, com, data);
PROC_UNLOCK(p);
@@ -932,7 +960,10 @@
first_error = 0;
LIST_FOREACH(p, &pg->pg_members, p_pglist) {
PROC_LOCK(p);
- if (p->p_state == PRS_NEW || p_cansee(td, p) != 0) {
+ if (p->p_state == PRS_NEW ||
+ p->p_state == PRS_ZOMBIE ||
+ (cmd_info->need_candebug ? p_candebug(td, p) :
+ p_cansee(td, p)) != 0) {
PROC_UNLOCK(p);
continue;
}
@@ -958,7 +989,14 @@
error = EINVAL;
break;
}
- if (tree_locked)
- sx_unlock(&proctree_lock);
+
+ switch (cmd_info->lock_tree) {
+ case SA_XLOCKED:
+ sx_xunlock(&proctree_lock);
+ break;
+ case SA_SLOCKED:
+ sx_sunlock(&proctree_lock);
+ break;
+ }
return (error);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Oct 12, 3:56 PM (21 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23629403
Default Alt Text
D32513.id97117.diff (22 KB)
Attached To
Mode
D32513: procctl: require debug privileges over the target for most of the _CTL commands
Attached
Detach File
Event Timeline
Log In to Comment