Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F168306827
D58586.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
35 KB
Referenced Files
None
Subscribers
None
D58586.diff
View Options
diff --git a/lib/libsys/Symbol.sys.map b/lib/libsys/Symbol.sys.map
--- a/lib/libsys/Symbol.sys.map
+++ b/lib/libsys/Symbol.sys.map
@@ -393,6 +393,7 @@
FBSD_1.9 {
pddupfd;
pdopenpid;
+ pdptrace;
pdrfork;
pdrfork_thread;
renameat2;
diff --git a/lib/libsys/_libsys.h b/lib/libsys/_libsys.h
--- a/lib/libsys/_libsys.h
+++ b/lib/libsys/_libsys.h
@@ -477,6 +477,7 @@
typedef int (__sys_renameat2_t)(int, const char *, int, const char *, int);
typedef int (__sys_pdopenpid_t)(pid_t, int);
typedef int (__sys_pddupfd_t)(int, int, int);
+typedef int (__sys_pdptrace_t)(int, int, int, void *, int);
_Noreturn void __sys__exit(int rval);
int __sys_fork(void);
@@ -889,6 +890,7 @@
int __sys_renameat2(int oldfd, const char * old, int newfd, const char * new, int flags);
int __sys_pdopenpid(pid_t pid, int flags);
int __sys_pddupfd(int pd, int fd, int flags);
+int __sys_pdptrace(int req, int pfd, int lwpid, void * addr, int data);
__END_DECLS
#endif /* __LIBSYS_H_ */
diff --git a/lib/libsys/pdfork.2 b/lib/libsys/pdfork.2
--- a/lib/libsys/pdfork.2
+++ b/lib/libsys/pdfork.2
@@ -66,6 +66,14 @@
.Fc
.Ft int
.Fn pddupfd "int fd" "int remotefd" "int flags"
+.Ft int
+.Fo pdptrace
+.Fa "int req"
+.Fa "int fd"
+.Fa "int lwpid"
+.Fa "void *addr"
+.Fa "int data"
+.Fc
.Sh DESCRIPTION
Process descriptors are special file descriptors that represent processes,
and are created using
@@ -83,7 +91,7 @@
.Fn pdfork
can accept the
.Fa pdflags:
-.Bl -tag -width PD_CLOEXEC
+.Bl -tag -width PD_PTRACE_CAP
.It Dv PD_DAEMON
Instead of the default terminate-on-close behaviour, allow the process to
live until it is explicitly killed with
@@ -106,6 +114,15 @@
.It Dv PD_NOWAITPID
The parent cannot obtain the child's status with
.Xr waitpid 2 .
+.It Dv PD_PTRACE_CAP
+Allows the
+.Xr pdptrace 2
+requests on the resulting file descriptor.
+See
+.Xr rights 4
+for the description of the
+.Dv CAP_PTRACE
+capability.
.El
.Pp
The
@@ -197,6 +214,20 @@
argument is reserved and must be zero.
Certain file descriptor types cannot be copied this way, namely
kqueues.
+.Pp
+The
+.Fn pdptrace
+function
+allows to execute the
+.Xr ptrace 2
+request on the process specified by the process descriptor
+.Fa fd .
+In addition to the arguments taken by the
+.Xr ptrace 2 ,
+the
+.Fa lwpid
+thread identifier can designate the thread on which the request
+must operate.
.Sh INTERACTION OF PROCESS DESCRIPTORS AND Xr WAITPID 2
.Pp
The
@@ -461,8 +492,9 @@
with input from
.An Alan Somers Aq Mt asomers@FreeBSD.org .
The
-.Fn pdopenpid
+.Fn pdopenpid ,
+.Fn pddupfd ,
and
-.Fn pddupfd
+.Fn pdptrace
functions were developed by
.An Konstantin Belousov Aq Mt kib@FreeBSD.org .
diff --git a/lib/libsys/syscalls.map b/lib/libsys/syscalls.map
--- a/lib/libsys/syscalls.map
+++ b/lib/libsys/syscalls.map
@@ -829,4 +829,6 @@
__sys_pdopenpid;
_pddupfd;
__sys_pddupfd;
+ _pdptrace;
+ __sys_pdptrace;
};
diff --git a/share/man/man4/rights.4 b/share/man/man4/rights.4
--- a/share/man/man4/rights.4
+++ b/share/man/man4/rights.4
@@ -484,6 +484,9 @@
.It Dv CAP_PDKILL
Permit
.Xr pdkill 2 .
+.It Dv CAP_PTRACE
+Permit debugging using
+.Xr pdptrace 2 .
.It Dv CAP_PDWAIT
Permit
.Xr pdwait 2 .
diff --git a/sys/bsm/audit_kevents.h b/sys/bsm/audit_kevents.h
--- a/sys/bsm/audit_kevents.h
+++ b/sys/bsm/audit_kevents.h
@@ -666,6 +666,7 @@
#define AUE_INOTIFY 43272 /* FreeBSD/Linux. */
#define AUE_PDRFORK 43273 /* FreeBSD-specific. */
#define AUE_PDOPENPID 43274 /* FreeBSD-specific. */
+#define AUE_PDPTRACE 43275 /* FreeBSD-specific. */
/*
* Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the
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
@@ -1015,8 +1015,9 @@
psr->sr_error = psr32->sr_error;
}
-int
-freebsd32_ptrace(struct thread *td, struct freebsd32_ptrace_args *uap)
+static int
+freebsd32_ptrace_copyinout(struct thread *td, int req, bool pd_mode, pid_t pid,
+ int pfd, lwpid_t lwpid, void *uaddr, int udata)
{
union {
struct ptrace_io_desc piod;
@@ -1050,39 +1051,32 @@
if (!allow_ptrace)
return (ENOSYS);
- error = 0;
- AUDIT_ARG_PID(uap->pid);
- AUDIT_ARG_CMD(uap->req);
- AUDIT_ARG_VALUE(uap->data);
+ error = 0;
addr = &r;
- data = uap->data;
- switch (uap->req) {
+ data = udata;
+
+ switch (req) {
case PT_GET_EVENT_MASK:
case PT_GET_SC_ARGS:
case PT_GET_SC_RET:
break;
case PT_SET_SC_RET:
- if (uap->data != sizeof(r32.psr)) {
- error = EINVAL;
- } else {
- error = copyin(uap->addr, &r32.psr, sizeof(r32.psr));
- if (error == 0)
- ptrace_sc_ret32_to_ret(&r32.psr, &r.psr);
- }
+ error = udata != sizeof(r32.psr) ? EINVAL :
+ copyin(uaddr, &r32.psr, sizeof(r32.psr));
+ if (error == 0)
+ ptrace_sc_ret32_to_ret(&r32.psr, &r.psr);
break;
case PT_LWPINFO:
- if (uap->data > sizeof(r32.pl))
+ if (udata > sizeof(r32.pl))
return (EINVAL);
-
/*
* Pass size of native structure in 'data'. Truncate
* if necessary to avoid siginfo.
*/
- data = sizeof(r.pl);
- if (uap->data < offsetof(struct ptrace_lwpinfo32, pl_siginfo) +
- sizeof(struct __siginfo32))
- data = offsetof(struct ptrace_lwpinfo, pl_siginfo);
+ data = udata < offsetof(struct ptrace_lwpinfo32,
+ pl_siginfo) + sizeof(struct __siginfo32) ?
+ offsetof(struct ptrace_lwpinfo, pl_siginfo) : sizeof(r.pl);
break;
case PT_GETREGS:
bzero(&r.reg, sizeof(r.reg));
@@ -1094,17 +1088,17 @@
bzero(&r.dbreg, sizeof(r.dbreg));
break;
case PT_SETREGS:
- error = copyin(uap->addr, &r.reg, sizeof(r.reg));
+ error = copyin(uaddr, &r.reg, sizeof(r.reg));
break;
case PT_SETFPREGS:
- error = copyin(uap->addr, &r.fpreg, sizeof(r.fpreg));
+ error = copyin(uaddr, &r.fpreg, sizeof(r.fpreg));
break;
case PT_SETDBREGS:
- error = copyin(uap->addr, &r.dbreg, sizeof(r.dbreg));
+ error = copyin(uaddr, &r.dbreg, sizeof(r.dbreg));
break;
case PT_GETREGSET:
case PT_SETREGSET:
- error = copyin(uap->addr, &r32.vec, sizeof(r32.vec));
+ error = copyin(uaddr, &r32.vec, sizeof(r32.vec));
if (error != 0)
break;
@@ -1112,14 +1106,12 @@
r.vec.iov_base = PTRIN(r32.vec.iov_base);
break;
case PT_SET_EVENT_MASK:
- if (uap->data != sizeof(r.ptevents))
- error = EINVAL;
- else
- error = copyin(uap->addr, &r.ptevents, uap->data);
+ error = udata != sizeof(r.ptevents) ? EINVAL :
+ copyin(uaddr, &r.ptevents, udata);
break;
case PT_IO:
- error = copyin(uap->addr, &r32.piod, sizeof(r32.piod));
- if (error)
+ error = copyin(uaddr, &r32.piod, sizeof(r32.piod));
+ if (error != 0)
break;
CP(r32.piod, r.piod, piod_op);
PTRIN_CP(r32.piod, r.piod, piod_offs);
@@ -1127,8 +1119,8 @@
CP(r32.piod, r.piod, piod_len);
break;
case PT_VM_ENTRY:
- error = copyin(uap->addr, &r32.pve, sizeof(r32.pve));
- if (error)
+ error = copyin(uaddr, &r32.pve, sizeof(r32.pve));
+ if (error != 0)
break;
CP(r32.pve, r.pve, pve_entry);
@@ -1143,21 +1135,18 @@
PTRIN_CP(r32.pve, r.pve, pve_path);
break;
case PT_COREDUMP:
- if (uap->data != sizeof(r32.pc))
- error = EINVAL;
- else
- error = copyin(uap->addr, &r32.pc, uap->data);
+ error = udata != sizeof(r32.pc) ? EINVAL :
+ copyin(uaddr, &r32.pc, udata);
+ if (error != 0)
+ break;
CP(r32.pc, r.pc, pc_fd);
CP(r32.pc, r.pc, pc_flags);
r.pc.pc_limit = PAIR32TO64(off_t, r32.pc.pc_limit);
data = sizeof(r.pc);
break;
case PT_SC_REMOTE:
- if (uap->data != sizeof(r32.sr)) {
- error = EINVAL;
- break;
- }
- error = copyin(uap->addr, &r32.sr, uap->data);
+ error = udata != sizeof(r32.sr) ? EINVAL :
+ copyin(uaddr, &r32.sr, udata);
if (error != 0)
break;
CP(r32.sr, r.sr, pscr_syscall);
@@ -1175,9 +1164,9 @@
r.sr.pscr_args = pscr_args;
break;
case PT_GET_CHILDREN:
- if (uap->addr == NULL)
+ if (uaddr == NULL)
addr = NULL;
- else if (uap->data < 0)
+ else if (udata < 0)
error = EINVAL;
else
addr = &r.children;
@@ -1186,17 +1175,17 @@
error = EINVAL;
break;
default:
- addr = uap->addr;
+ addr = uaddr;
break;
}
- if (error)
+ if (error != 0)
return (error);
- error = kern_ptrace(td, uap->req, uap->pid, addr, data);
- if (error)
+ error = ptrace_action(td, req, pd_mode, pid, pfd, lwpid, addr, data);
+ if (error != 0)
return (error);
- switch (uap->req) {
+ switch (req) {
case PT_VM_ENTRY:
CP(r.pve, r32.pve, pve_entry);
CP(r.pve, r32.pve, pve_timestamp);
@@ -1207,53 +1196,51 @@
CP(r.pve, r32.pve, pve_pathlen);
CP(r.pve, r32.pve, pve_fileid);
CP(r.pve, r32.pve, pve_fsid);
- error = copyout(&r32.pve, uap->addr, sizeof(r32.pve));
+ error = copyout(&r32.pve, uaddr, sizeof(r32.pve));
break;
case PT_IO:
CP(r.piod, r32.piod, piod_len);
- error = copyout(&r32.piod, uap->addr, sizeof(r32.piod));
+ error = copyout(&r32.piod, uaddr, sizeof(r32.piod));
break;
case PT_GETREGS:
- error = copyout(&r.reg, uap->addr, sizeof(r.reg));
+ error = copyout(&r.reg, uaddr, sizeof(r.reg));
break;
case PT_GETFPREGS:
- error = copyout(&r.fpreg, uap->addr, sizeof(r.fpreg));
+ error = copyout(&r.fpreg, uaddr, sizeof(r.fpreg));
break;
case PT_GETDBREGS:
- error = copyout(&r.dbreg, uap->addr, sizeof(r.dbreg));
+ error = copyout(&r.dbreg, uaddr, sizeof(r.dbreg));
break;
case PT_GETREGSET:
r32.vec.iov_len = r.vec.iov_len;
- error = copyout(&r32.vec, uap->addr, sizeof(r32.vec));
+ error = copyout(&r32.vec, uaddr, sizeof(r32.vec));
break;
case PT_GET_EVENT_MASK:
/* NB: The size in uap->data is validated in kern_ptrace(). */
- error = copyout(&r.ptevents, uap->addr, uap->data);
+ error = copyout(&r.ptevents, uaddr, udata);
break;
case PT_LWPINFO:
ptrace_lwpinfo_to32(&r.pl, &r32.pl);
- error = copyout(&r32.pl, uap->addr, uap->data);
+ error = copyout(&r32.pl, uaddr, udata);
break;
case PT_GET_SC_ARGS:
for (i = 0; i < nitems(r.args); i++)
r32.args[i] = (uint32_t)r.args[i];
- error = copyout(r32.args, uap->addr, MIN(uap->data,
- sizeof(r32.args)));
+ error = copyout(r32.args, uaddr, MIN(udata, sizeof(r32.args)));
break;
case PT_GET_SC_RET:
ptrace_sc_ret_to32(&r.psr, &r32.psr);
- error = copyout(&r32.psr, uap->addr, MIN(uap->data,
- sizeof(r32.psr)));
+ error = copyout(&r32.psr, uaddr, MIN(udata, sizeof(r32.psr)));
break;
case PT_SC_REMOTE:
ptrace_sc_ret_to32(&r.sr.pscr_ret, &r32.sr.pscr_ret);
- error = copyout(&r32.sr.pscr_ret, uap->addr +
+ error = copyout(&r32.sr.pscr_ret, (char *)uaddr +
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,
+ if (uaddr != NULL) {
+ error = copyout(r.children, uaddr,
td->td_retval[0] * sizeof(struct ptrace_child));
free(r.children, M_TEMP);
}
@@ -1263,6 +1250,31 @@
return (error);
}
+int
+freebsd32_ptrace(struct thread *td, struct freebsd32_ptrace_args *uap)
+{
+ int error;
+
+ AUDIT_ARG_PID(uap->pid);
+ AUDIT_ARG_CMD(uap->req);
+ AUDIT_ARG_VALUE(uap->data);
+
+ error = freebsd32_ptrace_copyinout(td, uap->req, false, uap->pid,
+ -1, -1, uap->addr, uap->data);
+ return (error);
+}
+
+int
+freebsd32_pdptrace(struct thread *td, struct freebsd32_pdptrace_args *uap)
+{
+ AUDIT_ARG_FD(uap->pfd);
+ AUDIT_ARG_CMD(uap->req);
+ AUDIT_ARG_VALUE(uap->data);
+
+ return (freebsd32_ptrace_copyinout(td, uap->req, true, -1,
+ uap->pfd, uap->lwpid, uap->addr, uap->data));
+}
+
int
freebsd32_copyinuio(const struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
{
diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h
--- a/sys/compat/freebsd32/freebsd32_proto.h
+++ b/sys/compat/freebsd32/freebsd32_proto.h
@@ -706,6 +706,13 @@
char wrusage_l_[PADL_(struct __wrusage32 *)]; struct __wrusage32 * wrusage; char wrusage_r_[PADR_(struct __wrusage32 *)];
char info_l_[PADL_(struct __siginfo32 *)]; struct __siginfo32 * info; char info_r_[PADR_(struct __siginfo32 *)];
};
+struct freebsd32_pdptrace_args {
+ char req_l_[PADL_(int)]; int req; char req_r_[PADR_(int)];
+ char pfd_l_[PADL_(int)]; int pfd; char pfd_r_[PADR_(int)];
+ char lwpid_l_[PADL_(int)]; int lwpid; char lwpid_r_[PADR_(int)];
+ char addr_l_[PADL_(void *)]; void * addr; char addr_r_[PADR_(void *)];
+ char data_l_[PADL_(int)]; int data; char data_r_[PADR_(int)];
+};
int freebsd32_wait4(struct thread *, struct freebsd32_wait4_args *);
int freebsd32_ptrace(struct thread *, struct freebsd32_ptrace_args *);
int freebsd32_recvmsg(struct thread *, struct freebsd32_recvmsg_args *);
@@ -825,6 +832,7 @@
int freebsd32_timerfd_settime(struct thread *, struct freebsd32_timerfd_settime_args *);
int freebsd32_setcred(struct thread *, struct freebsd32_setcred_args *);
int freebsd32_pdwait(struct thread *, struct freebsd32_pdwait_args *);
+int freebsd32_pdptrace(struct thread *, struct freebsd32_pdptrace_args *);
#ifdef COMPAT_43
@@ -1328,6 +1336,7 @@
#define FREEBSD32_SYS_AUE_freebsd32_timerfd_settime AUE_TIMERFD
#define FREEBSD32_SYS_AUE_freebsd32_setcred AUE_SETCRED
#define FREEBSD32_SYS_AUE_freebsd32_pdwait AUE_PDWAIT
+#define FREEBSD32_SYS_AUE_freebsd32_pdptrace AUE_PDPTRACE
#undef PAD_
#undef PADL_
diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h
--- a/sys/compat/freebsd32/freebsd32_syscall.h
+++ b/sys/compat/freebsd32/freebsd32_syscall.h
@@ -522,4 +522,5 @@
#define FREEBSD32_SYS_renameat2 602
#define FREEBSD32_SYS_pdopenpid 603
#define FREEBSD32_SYS_pddupfd 604
-#define FREEBSD32_SYS_MAXSYSCALL 605
+#define FREEBSD32_SYS_freebsd32_pdptrace 605
+#define FREEBSD32_SYS_MAXSYSCALL 606
diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c
--- a/sys/compat/freebsd32/freebsd32_syscalls.c
+++ b/sys/compat/freebsd32/freebsd32_syscalls.c
@@ -610,4 +610,5 @@
"renameat2", /* 602 = renameat2 */
"pdopenpid", /* 603 = pdopenpid */
"pddupfd", /* 604 = pddupfd */
+ "freebsd32_pdptrace", /* 605 = freebsd32_pdptrace */
};
diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c
--- a/sys/compat/freebsd32/freebsd32_sysent.c
+++ b/sys/compat/freebsd32/freebsd32_sysent.c
@@ -672,4 +672,5 @@
{ .sy_narg = AS(renameat2_args), .sy_call = (sy_call_t *)sys_renameat2, .sy_auevent = AUE_RENAMEAT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 602 = renameat2 */
{ .sy_narg = AS(pdopenpid_args), .sy_call = (sy_call_t *)sys_pdopenpid, .sy_auevent = AUE_PDOPENPID, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 603 = pdopenpid */
{ .sy_narg = AS(pddupfd_args), .sy_call = (sy_call_t *)sys_pddupfd, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 604 = pddupfd */
+ { .sy_narg = AS(freebsd32_pdptrace_args), .sy_call = (sy_call_t *)freebsd32_pdptrace, .sy_auevent = AUE_PDPTRACE, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 605 = freebsd32_pdptrace */
};
diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c
--- a/sys/compat/freebsd32/freebsd32_systrace_args.c
+++ b/sys/compat/freebsd32/freebsd32_systrace_args.c
@@ -3475,6 +3475,17 @@
*n_args = 3;
break;
}
+ /* freebsd32_pdptrace */
+ case 605: {
+ struct freebsd32_pdptrace_args *p = params;
+ iarg[a++] = p->req; /* int */
+ iarg[a++] = p->pfd; /* int */
+ iarg[a++] = p->lwpid; /* int */
+ uarg[a++] = (intptr_t)p->addr; /* void * */
+ iarg[a++] = p->data; /* int */
+ *n_args = 5;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -9393,6 +9404,28 @@
break;
};
break;
+ /* freebsd32_pdptrace */
+ case 605:
+ switch (ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "userland void *";
+ break;
+ case 4:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -11336,6 +11369,11 @@
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* freebsd32_pdptrace */
+ case 605:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
--- a/sys/kern/init_sysent.c
+++ b/sys/kern/init_sysent.c
@@ -671,4 +671,5 @@
{ .sy_narg = AS(renameat2_args), .sy_call = (sy_call_t *)sys_renameat2, .sy_auevent = AUE_RENAMEAT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 602 = renameat2 */
{ .sy_narg = AS(pdopenpid_args), .sy_call = (sy_call_t *)sys_pdopenpid, .sy_auevent = AUE_PDOPENPID, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 603 = pdopenpid */
{ .sy_narg = AS(pddupfd_args), .sy_call = (sy_call_t *)sys_pddupfd, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 604 = pddupfd */
+ { .sy_narg = AS(pdptrace_args), .sy_call = (sy_call_t *)sys_pdptrace, .sy_auevent = AUE_PDPTRACE, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 605 = pdptrace */
};
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -1906,7 +1906,7 @@
/*
* Fill the given filecaps structure with full rights.
*/
-static void
+void
filecaps_fill(struct filecaps *fcaps)
{
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -41,6 +41,7 @@
#include <sys/systm.h>
#include <sys/acct.h>
#include <sys/bitstring.h>
+#include <sys/capsicum.h>
#include <sys/eventhandler.h>
#include <sys/exterrvar.h>
#include <sys/fcntl.h>
@@ -119,6 +120,7 @@
sys_pdfork(struct thread *td, struct pdfork_args *uap)
{
struct fork_req fr;
+ struct filecaps fcaps;
int error, fd, pid;
bzero(&fr, sizeof(fr));
@@ -126,6 +128,10 @@
fr.fr_pidp = &pid;
fr.fr_pd_fd = &fd;
fr.fr_pd_flags = uap->flags;
+ filecaps_fill(&fcaps);
+ if ((uap->flags & PD_PTRACE_CAP) == 0)
+ cap_rights_clear(&fcaps.fc_rights, CAP_PTRACE);
+ fr.fr_pd_fcaps = &fcaps;
AUDIT_ARG_FFLAGS(uap->flags);
/*
* It is necessary to return fd by reference because 0 is a valid file
@@ -194,6 +200,7 @@
sys_pdrfork(struct thread *td, struct pdrfork_args *uap)
{
struct fork_req fr;
+ struct filecaps fcaps;
int error, fd, pid;
bzero(&fr, sizeof(fr));
@@ -226,6 +233,10 @@
fr.fr_pidp = &pid;
fr.fr_pd_fd = &fd;
fr.fr_pd_flags = uap->pdflags;
+ filecaps_fill(&fcaps);
+ if ((uap->pdflags & PD_PTRACE_CAP) == 0)
+ cap_rights_clear(&fcaps.fc_rights, CAP_PTRACE);
+ fr.fr_pd_fcaps = &fcaps;
error = fork1(td, &fr);
if (error == 0) {
td->td_retval[0] = pid;
@@ -1068,6 +1079,7 @@
fr->fr_pd_flags, fr->fr_pd_fcaps);
if (error != 0)
goto fail2;
+ fr->fr_pd_fcaps = NULL;
AUDIT_ARG_FD(*fr->fr_pd_fd);
}
@@ -1163,6 +1175,8 @@
fdclose(td, fp_procdesc, *fr->fr_pd_fd);
fdrop(fp_procdesc, td);
}
+ if (fr->fr_pd_fcaps != NULL)
+ filecaps_free(fr->fr_pd_fcaps);
atomic_add_int(&nprocs, -1);
cleanup:
if (killsx_locked)
diff --git a/sys/kern/subr_capability.c b/sys/kern/subr_capability.c
--- a/sys/kern/subr_capability.c
+++ b/sys/kern/subr_capability.c
@@ -93,6 +93,7 @@
const cap_rights_t cap_pdkill_rights = CAP_RIGHTS_INITIALIZER(CAP_PDKILL);
const cap_rights_t cap_pdwait_rights = CAP_RIGHTS_INITIALIZER(CAP_PDWAIT);
const cap_rights_t cap_pread_rights = CAP_RIGHTS_INITIALIZER(CAP_PREAD);
+const cap_rights_t cap_ptrace_rights = CAP_RIGHTS_INITIALIZER(CAP_PTRACE);
const cap_rights_t cap_pwrite_rights = CAP_RIGHTS_INITIALIZER(CAP_PWRITE);
const cap_rights_t cap_read_rights = CAP_RIGHTS_INITIALIZER(CAP_READ);
const cap_rights_t cap_recv_rights = CAP_RIGHTS_INITIALIZER(CAP_RECV);
diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c
--- a/sys/kern/sys_procdesc.c
+++ b/sys/kern/sys_procdesc.c
@@ -692,6 +692,7 @@
{
struct file *fp;
struct procdesc *pdf;
+ struct filecaps fcaps;
int error, fd, fflags;
error = falloc_noinstall(td, &fp);
@@ -701,13 +702,16 @@
pdf = procdesc_alloc(flags);
if ((flags & PD_DAEMON) != 0)
fp->f_pdflags |= F_PD_NOKILL;
+ filecaps_fill(&fcaps);
+ if ((flags & PD_PTRACE_CAP) == 0)
+ cap_rights_clear(&fcaps.fc_rights, CAP_PTRACE);
sx_xlock(&proctree_lock);
error = pdopenpid1(td, pid, &pdf, fp);
sx_xunlock(&proctree_lock);
if (error == 0) {
- error = finstall(td, fp, &fd, fflags, NULL);
+ error = finstall(td, fp, &fd, fflags, &fcaps);
if (error == 0) {
td->td_retval[0] = fd;
} else {
@@ -716,6 +720,7 @@
* return file descriptor to userspace.
*/
fp->f_pdflags |= F_PD_NOKILL | F_PD_NOFINSTALL;
+ filecaps_free(&fcaps);
}
}
fdrop(fp, td);
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
@@ -32,7 +32,7 @@
*/
#include <sys/systm.h>
-#include <sys/caprights.h>
+#include <sys/capsicum.h>
#include <sys/filedesc.h>
#include <sys/imgact.h>
#include <sys/ktr.h>
@@ -43,6 +43,7 @@
#include <sys/mutex.h>
#include <sys/priv.h>
#include <sys/proc.h>
+#include <sys/procdesc.h>
#include <sys/ptrace.h>
#include <sys/reg.h>
#include <sys/rwlock.h>
@@ -714,8 +715,9 @@
};
#endif
-int
-sys_ptrace(struct thread *td, struct ptrace_args *uap)
+static int
+ptrace_copyinout(struct thread *td, int req, bool pd_mode, pid_t pid, int pfd,
+ lwpid_t lwpid, void *uaddr, int udata)
{
/*
* XXX this obfuscation is to reduce stack usage, but the register
@@ -742,23 +744,19 @@
if (!allow_ptrace)
return (ENOSYS);
- error = 0;
- AUDIT_ARG_PID(uap->pid);
- AUDIT_ARG_CMD(uap->req);
- AUDIT_ARG_VALUE(uap->data);
+ error = 0;
addr = &r;
- switch (uap->req) {
+
+ switch (req) {
case PT_GET_EVENT_MASK:
case PT_LWPINFO:
case PT_GET_SC_ARGS:
case PT_GET_SC_RET:
break;
case PT_SET_SC_RET:
- if (uap->data != sizeof(r.psr))
- error = EINVAL;
- else
- error = copyin(uap->addr, &r.psr, sizeof(r.psr));
+ error = udata != sizeof(r.psr) ? EINVAL :
+ copyin(uaddr, &r.psr, sizeof(r.psr));
break;
case PT_GETREGS:
bzero(&r.reg, sizeof(r.reg));
@@ -771,41 +769,34 @@
break;
case PT_GETREGSET:
case PT_SETREGSET:
- error = copyin(uap->addr, &r.vec, sizeof(r.vec));
+ error = copyin(uaddr, &r.vec, sizeof(r.vec));
break;
case PT_SETREGS:
- error = copyin(uap->addr, &r.reg, sizeof(r.reg));
+ error = copyin(uaddr, &r.reg, sizeof(r.reg));
break;
case PT_SETFPREGS:
- error = copyin(uap->addr, &r.fpreg, sizeof(r.fpreg));
+ error = copyin(uaddr, &r.fpreg, sizeof(r.fpreg));
break;
case PT_SETDBREGS:
- error = copyin(uap->addr, &r.dbreg, sizeof(r.dbreg));
+ error = copyin(uaddr, &r.dbreg, sizeof(r.dbreg));
break;
case PT_SET_EVENT_MASK:
- if (uap->data != sizeof(r.ptevents))
- error = EINVAL;
- else
- error = copyin(uap->addr, &r.ptevents, uap->data);
+ error = udata != sizeof(r.ptevents) ? EINVAL :
+ copyin(uaddr, &r.ptevents, udata);
break;
case PT_IO:
- error = copyin(uap->addr, &r.piod, sizeof(r.piod));
+ error = copyin(uaddr, &r.piod, sizeof(r.piod));
break;
case PT_VM_ENTRY:
- error = copyin(uap->addr, &r.pve, sizeof(r.pve));
+ error = copyin(uaddr, &r.pve, sizeof(r.pve));
break;
case PT_COREDUMP:
- if (uap->data != sizeof(r.pc))
- error = EINVAL;
- else
- error = copyin(uap->addr, &r.pc, uap->data);
+ error = udata != sizeof(r.pc) ? EINVAL :
+ copyin(uaddr, &r.pc, udata);
break;
case PT_SC_REMOTE:
- if (uap->data != sizeof(r.sr)) {
- error = EINVAL;
- break;
- }
- error = copyin(uap->addr, &r.sr, uap->data);
+ error = udata != sizeof(r.sr) ? EINVAL :
+ copyin(uaddr, &r.sr, udata);
if (error != 0)
break;
if (r.sr.pscr_nargs > nitems(td->td_sa.args)) {
@@ -819,9 +810,9 @@
r.sr.pscr_args = pscr_args;
break;
case PT_GET_CHILDREN:
- if (uap->addr == NULL)
+ if (uaddr == NULL)
addr = NULL;
- else if (uap->data < 0)
+ else if (udata < 0)
error = EINVAL;
else
addr = &r.children;
@@ -830,59 +821,57 @@
error = EINVAL;
break;
default:
- addr = uap->addr;
+ addr = uaddr;
break;
}
if (error != 0)
return (error);
- error = kern_ptrace(td, uap->req, uap->pid, addr, uap->data);
+ error = ptrace_action(td, req, pd_mode, pid, pfd, lwpid, addr, udata);
if (error != 0)
return (error);
- switch (uap->req) {
+ switch (req) {
case PT_VM_ENTRY:
- error = copyout(&r.pve, uap->addr, sizeof(r.pve));
+ error = copyout(&r.pve, uaddr, sizeof(r.pve));
break;
case PT_IO:
- error = copyout(&r.piod, uap->addr, sizeof(r.piod));
+ error = copyout(&r.piod, uaddr, sizeof(r.piod));
break;
case PT_GETREGS:
- error = copyout(&r.reg, uap->addr, sizeof(r.reg));
+ error = copyout(&r.reg, uaddr, sizeof(r.reg));
break;
case PT_GETFPREGS:
- error = copyout(&r.fpreg, uap->addr, sizeof(r.fpreg));
+ error = copyout(&r.fpreg, uaddr, sizeof(r.fpreg));
break;
case PT_GETDBREGS:
- error = copyout(&r.dbreg, uap->addr, sizeof(r.dbreg));
+ error = copyout(&r.dbreg, uaddr, sizeof(r.dbreg));
break;
case PT_GETREGSET:
- error = copyout(&r.vec, uap->addr, sizeof(r.vec));
+ error = copyout(&r.vec, uaddr, sizeof(r.vec));
break;
case PT_GET_EVENT_MASK:
- /* NB: The size in uap->data is validated in kern_ptrace(). */
- error = copyout(&r.ptevents, uap->addr, uap->data);
+ /* NB: The size in uap->data is validated in ptraceimpl(). */
+ error = copyout(&r.ptevents, uaddr, udata);
break;
case PT_LWPINFO:
- /* NB: The size in uap->data is validated in kern_ptrace(). */
- error = copyout(&r.pl, uap->addr, uap->data);
+ /* NB: The size in uap->data is validated in ptraceimpl(). */
+ error = copyout(&r.pl, uaddr, udata);
break;
case PT_GET_SC_ARGS:
- error = copyout(r.args, uap->addr, MIN(uap->data,
- sizeof(r.args)));
+ error = copyout(r.args, uaddr, MIN(udata, sizeof(r.args)));
break;
case PT_GET_SC_RET:
- error = copyout(&r.psr, uap->addr, MIN(uap->data,
- sizeof(r.psr)));
+ error = copyout(&r.psr, uaddr, MIN(udata, sizeof(r.psr)));
break;
case PT_SC_REMOTE:
- error = copyout(&r.sr.pscr_ret, uap->addr +
+ error = copyout(&r.sr.pscr_ret, (char *)uaddr +
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,
+ if (uaddr != NULL) {
+ error = copyout(r.children, uaddr,
td->td_retval[0] * sizeof(struct ptrace_child));
free(r.children, M_TEMP);
}
@@ -1056,7 +1045,8 @@
}
int
-kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
+ptrace_action(struct thread *td, int req, bool pd_mode, pid_t pid, int pfd,
+ lwpid_t lwpid, void *addr, int data)
{
struct iovec iov;
struct uio uio;
@@ -1070,6 +1060,7 @@
struct ptrace_coredump *pc;
struct thr_coredump_req *tcq;
struct thr_syscall_req *tsr;
+ struct file *pfp;
struct ptrace_child *children, *ptc;
int error, num, num1, tmp;
lwpid_t tid = 0, *buf;
@@ -1081,6 +1072,7 @@
curp = td->td_proc;
proctree_locked = false;
p2_req_set = false;
+ pfp = NULL;
/* Lock proctree before locking the process. */
switch (req) {
@@ -1108,24 +1100,42 @@
if (req == PT_TRACE_ME) {
p = td->td_proc;
PROC_LOCK(p);
- } else {
- if (pid <= PID_MAX) {
- if ((p = pfind(pid)) == NULL) {
- if (proctree_locked)
- sx_xunlock(&proctree_lock);
- return (ESRCH);
+ } else if (pd_mode) {
+ if (!proctree_locked)
+ sx_slock(&proctree_lock);
+ error = fget_procdesc(td, pfd, &cap_ptrace_rights, EINVAL,
+ &pfp, NULL, &p);
+ if (!proctree_locked)
+ sx_sunlock(&proctree_lock);
+ if (error != 0)
+ goto fail_proctree;
+ pid = p->p_pid;
+ if (lwpid != -1) {
+ FOREACH_THREAD_IN_PROC(p, td2) {
+ if (td2->td_tid == lwpid)
+ break;
}
- } else {
- td2 = tdfind(pid, -1);
if (td2 == NULL) {
- if (proctree_locked)
- sx_xunlock(&proctree_lock);
- return (ESRCH);
+ PROC_UNLOCK(p);
+ error = ESRCH;
+ goto fail_proctree;
}
- p = td2->td_proc;
- tid = pid;
- pid = p->p_pid;
+ tid = td->td_tid;
}
+ } else if (pid <= PID_MAX) {
+ if ((p = pfind(pid)) == NULL) {
+ error = ESRCH;
+ goto fail_proctree;
+ }
+ } else {
+ td2 = tdfind(pid, -1);
+ if (td2 == NULL) {
+ error = ESRCH;
+ goto fail_proctree;
+ }
+ p = td2->td_proc;
+ tid = pid;
+ pid = p->p_pid;
}
AUDIT_ARG_PROCESS(p);
@@ -2021,9 +2031,46 @@
p->p_flag2 &= ~P2_PTRACEREQ;
}
PROC_UNLOCK(p);
+fail_proctree:
if (proctree_locked)
sx_xunlock(&proctree_lock);
+ if (pfp != NULL)
+ fdrop(pfp, td);
return (error);
}
#undef PROC_READ
#undef PROC_WRITE
+
+int
+kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
+{
+ return (ptrace_action(td, req, pid, false, -1, -1, addr, data));
+}
+
+int
+sys_ptrace(struct thread *td, struct ptrace_args *uap)
+{
+ int error;
+
+ AUDIT_ARG_PID(uap->pid);
+ AUDIT_ARG_CMD(uap->req);
+ AUDIT_ARG_VALUE(uap->data);
+
+ error = ptrace_copyinout(td, uap->req, false, uap->pid, -1, -1,
+ uap->addr, uap->data);
+ return (error);
+}
+
+int
+sys_pdptrace(struct thread *td, struct pdptrace_args *uap)
+{
+ int error;
+
+ AUDIT_ARG_FD(uap->pfd);
+ AUDIT_ARG_CMD(uap->req);
+ AUDIT_ARG_VALUE(uap->data);
+
+ error = ptrace_copyinout(td, uap->req, true, -1, uap->pfd, uap->lwpid,
+ uap->addr, uap->data);
+ return (error);
+}
diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c
--- a/sys/kern/syscalls.c
+++ b/sys/kern/syscalls.c
@@ -610,4 +610,5 @@
"renameat2", /* 602 = renameat2 */
"pdopenpid", /* 603 = pdopenpid */
"pddupfd", /* 604 = pddupfd */
+ "pdptrace", /* 605 = pdptrace */
};
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -3442,5 +3442,14 @@
int flags
);
}
+605 AUE_PDPTRACE STD {
+ int pdptrace(
+ int req,
+ int pfd,
+ int lwpid,
+ _Inout_opt_ _Contains_long_ptr_ void *addr,
+ int data
+ );
+ }
; vim: syntax=off
diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c
--- a/sys/kern/systrace_args.c
+++ b/sys/kern/systrace_args.c
@@ -3572,6 +3572,17 @@
*n_args = 3;
break;
}
+ /* pdptrace */
+ case 605: {
+ struct pdptrace_args *p = params;
+ iarg[a++] = p->req; /* int */
+ iarg[a++] = p->pfd; /* int */
+ iarg[a++] = p->lwpid; /* int */
+ uarg[a++] = (intptr_t)p->addr; /* void * */
+ iarg[a++] = p->data; /* int */
+ *n_args = 5;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -9567,6 +9578,28 @@
break;
};
break;
+ /* pdptrace */
+ case 605:
+ switch (ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "userland void *";
+ break;
+ case 4:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -11605,6 +11638,11 @@
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* pdptrace */
+ case 605:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
diff --git a/sys/sys/caprights.h b/sys/sys/caprights.h
--- a/sys/sys/caprights.h
+++ b/sys/sys/caprights.h
@@ -95,6 +95,7 @@
extern const cap_rights_t cap_pdkill_rights;
extern const cap_rights_t cap_pdwait_rights;
extern const cap_rights_t cap_pread_rights;
+extern const cap_rights_t cap_ptrace_rights;
extern const cap_rights_t cap_pwrite_rights;
extern const cap_rights_t cap_read_rights;
extern const cap_rights_t cap_recv_rights;
diff --git a/sys/sys/capsicum.h b/sys/sys/capsicum.h
--- a/sys/sys/capsicum.h
+++ b/sys/sys/capsicum.h
@@ -299,7 +299,9 @@
/* Allows pddupfd(2). */
#define CAP_PDDUPFD CAPRIGHT(1, 0x0000000000800000ULL)
-#define CAP_UNUSED1_25 CAPRIGHT(1, 0x0000000001000000ULL)
+/* Allows ptrace(PT_PROCDESC) */
+#define CAP_PTRACE CAPRIGHT(1, 0x0000000001000000ULL)
+
#define CAP_UNUSED1_26 CAPRIGHT(1, 0x0000000002000000ULL)
#define CAP_UNUSED1_27 CAPRIGHT(1, 0x0000000004000000ULL)
#define CAP_UNUSED1_28 CAPRIGHT(1, 0x0000000008000000ULL)
@@ -333,8 +335,8 @@
#define CAP_UNUSED1_56 CAPRIGHT(1, 0x0080000000000000ULL)
#define CAP_UNUSED1_57 CAPRIGHT(1, 0x0100000000000000ULL)
-/* All used bits for index 1. */
-#define CAP_ALL1 CAPRIGHT(1, 0x0000000000FFFFFFULL)
+/* All default bits for index 1. */
+#define CAP_ALL1 CAPRIGHT(1, 0x0000000001FFFFFFULL)
/* Backward compatibility. */
#define CAP_POLL_EVENT CAP_EVENT
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -243,6 +243,7 @@
bool filecaps_copy(const struct filecaps *src, struct filecaps *dst,
bool locked);
void filecaps_move(struct filecaps *src, struct filecaps *dst);
+void filecaps_fill(struct filecaps *fcaps);
void filecaps_free(struct filecaps *fcaps);
int closef(struct file *fp, struct thread *td);
diff --git a/sys/sys/procdesc.h b/sys/sys/procdesc.h
--- a/sys/sys/procdesc.h
+++ b/sys/sys/procdesc.h
@@ -151,6 +151,7 @@
int pdwait(int, int *, int, struct __wrusage *, struct __siginfo *);
int pddupfd(int, int, int);
pid_t pdrfork_thread(int *, int, int, void *, int (*)(void *), void *);
+int pdptrace(int, int, int, void *, int);
__END_DECLS
#endif /* _KERNEL */
@@ -161,8 +162,10 @@
#define PD_DAEMON 0x00000001 /* Don't exit when procdesc closes. */
#define PD_CLOEXEC 0x00000002 /* Close file descriptor on exec. */
#define PD_NOWAITPID 0x00000004 /* Reap without waitpid(). */
+#define PD_PTRACE_CAP 0x00000008 /* Allow PT_PROCDESC in cap mode. */
-#define PD_ALLOWED_AT_FORK (PD_DAEMON | PD_CLOEXEC | PD_NOWAITPID)
-#define PD_ALLOWED_AT_OPENPID (PD_DAEMON | PD_CLOEXEC)
+#define PD_ALLOWED_AT_FORK \
+ (PD_DAEMON | PD_CLOEXEC | PD_NOWAITPID | PD_PTRACE_CAP)
+#define PD_ALLOWED_AT_OPENPID (PD_DAEMON | PD_CLOEXEC | PD_PTRACE_CAP)
#endif /* !_SYS_PROCDESC_H_ */
diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h
--- a/sys/sys/ptrace.h
+++ b/sys/sys/ptrace.h
@@ -291,6 +291,8 @@
#endif
void ptrace_unsuspend(struct proc *p);
+int ptrace_action(struct thread *td, int req, bool pd_mode, pid_t pid,
+ int pfd, lwpid_t lwpid, void *addr, int data);
extern bool allow_ptrace;
diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h
--- a/sys/sys/syscall.h
+++ b/sys/sys/syscall.h
@@ -543,4 +543,5 @@
#define SYS_renameat2 602
#define SYS_pdopenpid 603
#define SYS_pddupfd 604
-#define SYS_MAXSYSCALL 605
+#define SYS_pdptrace 605
+#define SYS_MAXSYSCALL 606
diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk
--- a/sys/sys/syscall.mk
+++ b/sys/sys/syscall.mk
@@ -446,4 +446,5 @@
pdwait.o \
renameat2.o \
pdopenpid.o \
- pddupfd.o
+ pddupfd.o \
+ pdptrace.o
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -299,6 +299,8 @@
off_t len);
int kern_fspacectl(struct thread *td, int fd, int cmd,
const struct spacectl_range *, int flags, struct spacectl_range *);
+int kern_pdptrace(struct thread *td, int req, int pfd, void *addr,
+ int data);
int kern_pdwait(struct thread *td, int fd, int *status,
int options, struct __wrusage *wrusage, siginfo_t *sip);
int kern_procctl(struct thread *td, enum idtype idtype, id_t id, int com,
diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h
--- a/sys/sys/sysproto.h
+++ b/sys/sys/sysproto.h
@@ -1941,6 +1941,13 @@
char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
};
+struct pdptrace_args {
+ char req_l_[PADL_(int)]; int req; char req_r_[PADR_(int)];
+ char pfd_l_[PADL_(int)]; int pfd; char pfd_r_[PADR_(int)];
+ char lwpid_l_[PADL_(int)]; int lwpid; char lwpid_r_[PADR_(int)];
+ char addr_l_[PADL_(void *)]; void * addr; char addr_r_[PADR_(void *)];
+ char data_l_[PADL_(int)]; int data; char data_r_[PADR_(int)];
+};
int sys__exit(struct thread *, struct _exit_args *);
int sys_fork(struct thread *, struct fork_args *);
int sys_read(struct thread *, struct read_args *);
@@ -2353,6 +2360,7 @@
int sys_renameat2(struct thread *, struct renameat2_args *);
int sys_pdopenpid(struct thread *, struct pdopenpid_args *);
int sys_pddupfd(struct thread *, struct pddupfd_args *);
+int sys_pdptrace(struct thread *, struct pdptrace_args *);
#ifdef COMPAT_43
@@ -3357,6 +3365,7 @@
#define SYS_AUE_renameat2 AUE_RENAMEAT
#define SYS_AUE_pdopenpid AUE_PDOPENPID
#define SYS_AUE_pddupfd AUE_NULL
+#define SYS_AUE_pdptrace AUE_PDPTRACE
#undef PAD_
#undef PADL_
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Aug 28, 1:36 PM (3 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37456091
Default Alt Text
D58586.diff (35 KB)
Attached To
Mode
D58586: pdptrace(2)
Attached
Detach File
Event Timeline
Log In to Comment