Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F164331135
D58315.id182238.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D58315.id182238.diff
View Options
diff --git a/lib/libsys/ptrace.2 b/lib/libsys/ptrace.2
--- a/lib/libsys/ptrace.2
+++ b/lib/libsys/ptrace.2
@@ -1044,6 +1044,57 @@
member.
Note that the request and its result do not affect the returned value from
the currently executed syscall, if any.
+.It Dv PT_GET_CHILDREN
+Returns the report of the children for the specified
+.Fa pid ,
+visible to the current process.
+.Pp
+If the
+.Fa addr
+argument is
+.Dv NULL ,
+the estimated number of the children is returned as the
+request result.
+.Pp
+If the
+.Fa addr
+argument is not
+.Dv NULL ,
+it must point to the array of the
+.Bd -literal
+struct ptrace_child {
+ pid_t pid;
+ int flags;
+};
+.Ed
+elements, the size of the array in bytes must be passed in
+.Fa data.
+The request fills the array and returns the number of elements filled.
+.Pp
+For each element, the
+.Va pid
+member contains the PID of the child.
+The
+.Va flags
+member may have the following flags reported:
+.Bl -tag -width PTCHLD_TRACED
+.It Dv PTCHLD_TRACED
+The child specified by the
+.Va pid
+member is traced.
+.It Dv PTCHLD_TRACED_BY_ME
+The child specified by the
+.Va pid
+member is traced
+by the caller (not the
+process specified by the
+.Fa pid
+argument to the function).
+.It Dv PTCHLD_EXITED
+The child process is exiting or zombie.
+.It Dv PTCHLD_ORPHAN
+The child process was temporarily reparented to its debugger.
+.El
.El
.Sh PT_COREDUMP and PT_SC_REMOTE usage
The process must be stopped before dumping or initiating a remote system call.
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -1031,6 +1031,7 @@
register_t args[nitems(td->td_sa.args)];
struct ptrace_sc_ret psr;
int ptevents;
+ struct ptrace_child *children;
} r;
union {
struct ptrace_io_desc32 piod;
@@ -1173,6 +1174,9 @@
pscr_args[i] = pscr_args32[i];
r.sr.pscr_args = pscr_args;
break;
+ case PT_GET_CHILDREN:
+ addr = uap->addr == NULL ? NULL : &r.children;
+ break;
case PTINTERNAL_FIRST ... PTINTERNAL_LAST:
error = EINVAL;
break;
@@ -1242,6 +1246,13 @@
offsetof(struct ptrace_sc_remote32, pscr_ret),
sizeof(r32.psr));
break;
+ case PT_GET_CHILDREN:
+ if (uap->addr != 0) {
+ error = copyout(r.children, uap->addr,
+ td->td_retval[0] * sizeof(struct ptrace_child));
+ free(r.children, M_TEMP);
+ }
+ break;
}
return (error);
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -733,6 +733,7 @@
syscallarg_t args[nitems(td->td_sa.args)];
struct ptrace_sc_ret psr;
int ptevents;
+ struct ptrace_child *children;
} r;
syscallarg_t pscr_args[nitems(td->td_sa.args)];
void *addr;
@@ -816,6 +817,9 @@
break;
r.sr.pscr_args = pscr_args;
break;
+ case PT_GET_CHILDREN:
+ addr = uap->addr == NULL ? NULL : &r.children;
+ break;
case PTINTERNAL_FIRST ... PTINTERNAL_LAST:
error = EINVAL;
break;
@@ -870,6 +874,13 @@
offsetof(struct ptrace_sc_remote, pscr_ret),
sizeof(r.sr.pscr_ret));
break;
+ case PT_GET_CHILDREN:
+ if (uap->addr != NULL) {
+ error = copyout(r.children, uap->addr,
+ td->td_retval[0] * sizeof(struct ptrace_child));
+ free(r.children, M_TEMP);
+ }
+ break;
}
return (error);
@@ -965,6 +976,56 @@
return (0);
}
+static int
+ptrace_count_children(struct thread *td, struct proc *p)
+{
+ struct proc *pp;
+ int error, num;
+
+ sx_assert(&proctree_lock, SX_LOCKED);
+ num = 0;
+ LIST_FOREACH(pp, &p->p_children, p_sibling) {
+ PROC_LOCK(pp);
+ error = p_cansee(td, pp);
+ PROC_UNLOCK(pp);
+ if (error != 0)
+ continue;
+ num++;
+ }
+ LIST_FOREACH(pp, &p->p_orphans, p_orphan) {
+ PROC_LOCK(pp);
+ error = p_cansee(td, pp);
+ PROC_UNLOCK(pp);
+ if (error != 0)
+ continue;
+ num++;
+ }
+ return (num);
+}
+
+static bool
+ptrace_report_child(struct thread *td, struct proc *p, struct proc *pp,
+ struct ptrace_child *ptc)
+{
+ sx_assert(&proctree_lock, SX_LOCKED);
+
+ PROC_LOCK(pp);
+ if (p_cansee(td, pp) != 0) {
+ PROC_UNLOCK(pp);
+ return (false);
+ }
+ ptc->pid = pp->p_pid;
+ if ((pp->p_flag & P_TRACED) != 0) {
+ ptc->flags |= PTCHLD_TRACED;
+ if (pp->p_pptr == p)
+ ptc->flags |= PTCHLD_TRACED_BY_ME;
+ }
+ if ((pp->p_flag & P_WEXIT) != 0)
+ ptc->flags |= PTCHLD_EXITED;
+ PROC_UNLOCK(pp);
+ return (true);
+}
+
static struct thread *
ptrace_sel_coredump_thread(struct proc *p)
{
@@ -995,7 +1056,8 @@
struct ptrace_coredump *pc;
struct thr_coredump_req *tcq;
struct thr_syscall_req *tsr;
- int error, num, tmp;
+ struct ptrace_child *children, *ptc;
+ int error, num, num1, tmp;
lwpid_t tid = 0, *buf;
#ifdef COMPAT_FREEBSD32
int wrap32 = 0, safe = 0;
@@ -1021,6 +1083,7 @@
case PT_SET_EVENT_MASK:
case PT_DETACH:
case PT_GET_SC_ARGS:
+ case PT_GET_CHILDREN:
sx_xlock(&proctree_lock);
proctree_locked = true;
break;
@@ -1132,8 +1195,14 @@
/* Allow thread to clear single step for itself */
if (td->td_tid == tid)
break;
+ goto default_check;
- /* FALLTHROUGH */
+ case PT_GET_CHILDREN:
+ if (p == curp)
+ break;
+ goto default_check;
+
+default_check:
default:
/*
* Check for ptrace eligibility before waiting for
@@ -1864,6 +1933,50 @@
free(tsr, M_TEMP);
break;
+ case PT_GET_CHILDREN:
+ PROC_UNLOCK(p);
+get_children_repeat:
+ num = ptrace_count_children(td, p);
+ if (addr == NULL) {
+ td->td_retval[0] = num;
+ PROC_LOCK(p);
+ break;
+ }
+ if (data < num * sizeof(struct ptrace_child)) {
+ error = ENOMEM;
+ PROC_LOCK(p);
+ break;
+ }
+ sx_xunlock(&proctree_lock);
+ children = mallocarray(num, sizeof(struct ptrace_child),
+ M_TEMP, M_WAITOK | M_ZERO);
+ sx_xlock(&proctree_lock);
+ num1 = ptrace_count_children(td, p);
+ if (num1 > num) {
+ free(children, M_TEMP);
+ goto get_children_repeat;
+ }
+ num = num1;
+ num1 = 0;
+ td->td_retval[0] = num;
+ LIST_FOREACH(pp, &p->p_children, p_sibling) {
+ MPASS(num1 < num);
+ ptc = &children[num1];
+ if (ptrace_report_child(td, p, pp, ptc))
+ num1++;
+ }
+ LIST_FOREACH(pp, &p->p_orphans, p_orphan) {
+ MPASS(num1 < num);
+ ptc = &children[num1];
+ if (ptrace_report_child(td, p, pp, ptc)) {
+ num1++;
+ ptc->flags |= PTCHLD_ORPHAN;
+ }
+ }
+ *(struct ptrace_child **)addr = children;
+ PROC_LOCK(p);
+ break;
+
default:
#ifdef __HAVE_PTRACE_MACHDEP
if (req >= PT_FIRSTMACH) {
diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h
--- a/sys/sys/ptrace.h
+++ b/sys/sys/ptrace.h
@@ -86,6 +86,7 @@
#define PT_SETREGSET 43 /* Set a target register set */
#define PT_SC_REMOTE 44 /* Execute a syscall */
#define PT_SET_SC_RET 45 /* Set (fake) syscall results */
+#define PT_GET_CHILDREN 46 /* Report children */
#define PT_FIRSTMACH 64 /* for machine-specific requests */
#define PT_LASTMACH 127
@@ -206,6 +207,17 @@
syscallarg_t *pscr_args;
};
+#define PTCHLD_TRACED 0x00000001
+#define PTCHLD_TRACED_BY_ME 0x00000002
+#define PTCHLD_EXITED 0x00000004
+#define PTCHLD_ORPHAN 0x00000008
+
+struct ptrace_child {
+ pid_t pid;
+ int flags;
+ uintptr_t rsrv[3];
+};
+
#ifdef _KERNEL
#include <sys/proc.h>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jul 31, 9:17 PM (11 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35796887
Default Alt Text
D58315.id182238.diff (7 KB)
Attached To
Mode
D58315: ptrace(2): add PT_GET_CHILDREN
Attached
Detach File
Event Timeline
Log In to Comment