Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F164678488
D58586.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
21 KB
Referenced Files
None
Subscribers
None
D58586.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
@@ -131,10 +131,19 @@
Similarly, for operations affecting only a thread, the thread ID
needs to be passed.
.Pp
+If the
+.Fa request
+argument is or-ed with the
+.Dv PT_PROCDESC
+flag, then the
+.Fa pid
+argument is interpreted as the process descriptor.
+The call operates on the process referenced by the descriptor.
+.Pp
Still, for global operations, the ID of any thread can be used as the
target, and system will perform the request on the process owning
that thread.
-If a thread operation got the process ID as
+If a thread operation got the process ID or the process descriptor as
.Fa pid ,
the system randomly selects a thread from among the threads owned
by the process.
diff --git a/sys/amd64/linux/linux_machdep.c b/sys/amd64/linux/linux_machdep.c
--- a/sys/amd64/linux/linux_machdep.c
+++ b/sys/amd64/linux/linux_machdep.c
@@ -326,7 +326,8 @@
l_regset->fs_base = pcb->pcb_fsbase;
l_regset->gs_base = pcb->pcb_gsbase;
- error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo));
+ error = kern_ptrace(td, false, PT_LWPINFO, pid, &lwpinfo,
+ sizeof(lwpinfo));
if (error != 0) {
linux_msg(td, "PT_LWPINFO failed with error %d", error);
return (error);
@@ -362,10 +363,10 @@
}
if (LINUX_URO(addr, fs_base))
- return (kern_ptrace(td, PT_GETFSBASE, pid, data, 0));
+ return (kern_ptrace(td, false, PT_GETFSBASE, pid, data, 0));
if (LINUX_URO(addr, gs_base))
- return (kern_ptrace(td, PT_GETGSBASE, pid, data, 0));
- if ((error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0)) != 0)
+ return (kern_ptrace(td, false, PT_GETGSBASE, pid, data, 0));
+ if ((error = kern_ptrace(td, false, PT_GETREGS, pid, &b_reg, 0)) != 0)
return (error);
bsd_to_linux_regset(&b_reg, ®);
val = *(®.r15 + ((uintptr_t)addr / sizeof(reg.r15)));
@@ -427,9 +428,9 @@
}
if (LINUX_URO(addr, fs_base))
- return (kern_ptrace(td, PT_SETFSBASE, pid, data, 0));
+ return (kern_ptrace(td, false, PT_SETFSBASE, pid, data, 0));
if (LINUX_URO(addr, gs_base))
- return (kern_ptrace(td, PT_SETGSBASE, pid, data, 0));
+ return (kern_ptrace(td, false, PT_SETGSBASE, pid, data, 0));
for (i = 0; i < nitems(linux_segregs_off); i++) {
if ((uintptr_t)addr == linux_segregs_off[i].reg) {
if (linux_invalid_selector((uintptr_t)data))
@@ -438,13 +439,13 @@
return (EIO);
}
}
- if ((error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0)) != 0)
+ if ((error = kern_ptrace(td, false, PT_GETREGS, pid, &b_reg, 0)) != 0)
return (error);
bsd_to_linux_regset(&b_reg, ®);
*(®.r15 + ((uintptr_t)addr / sizeof(reg.r15))) = (uint64_t)data;
linux_to_bsd_regset(&b_reg1, ®);
b_reg1.r_err = b_reg.r_err;
b_reg1.r_trapno = b_reg.r_trapno;
- return (kern_ptrace(td, PT_SETREGS, pid, &b_reg, 0));
+ return (kern_ptrace(td, false, PT_SETREGS, pid, &b_reg, 0));
}
#undef LINUX_URO
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
@@ -1047,6 +1047,7 @@
u_int pscr_args32[nitems(td->td_sa.args)];
void *addr;
int data, error, i;
+ bool pd_mode;
if (!allow_ptrace)
return (ENOSYS);
@@ -1057,6 +1058,9 @@
AUDIT_ARG_VALUE(uap->data);
addr = &r;
data = uap->data;
+ pd_mode = (uap->req & PT_PROCDESC) != 0;
+ uap->req &= ~PT_PROCDESC;
+
switch (uap->req) {
case PT_GET_EVENT_MASK:
case PT_GET_SC_ARGS:
@@ -1192,7 +1196,7 @@
if (error)
return (error);
- error = kern_ptrace(td, uap->req, uap->pid, addr, data);
+ error = kern_ptrace(td, pd_mode, uap->req, uap->pid, addr, data);
if (error)
return (error);
diff --git a/sys/compat/linux/linux_ptrace.c b/sys/compat/linux/linux_ptrace.c
--- a/sys/compat/linux/linux_ptrace.c
+++ b/sys/compat/linux/linux_ptrace.c
@@ -127,7 +127,8 @@
int error;
saved_retval = td->td_retval[0];
- error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo));
+ error = kern_ptrace(td, false, PT_LWPINFO, pid, &lwpinfo,
+ sizeof(lwpinfo));
td->td_retval[0] = saved_retval;
if (error != 0) {
linux_msg(td, "PT_LWPINFO failed with error %d", error);
@@ -161,7 +162,7 @@
{
int error;
- error = kern_ptrace(td, PT_READ_I, pid, addr, 0);
+ error = kern_ptrace(td, false, PT_READ_I, pid, addr, 0);
if (error == 0)
error = copyout(td->td_retval, data, sizeof(l_int));
else if (error == ENOMEM)
@@ -222,7 +223,8 @@
pem->ptrace_flags &= ~LINUX_PTRACE_O_TRACEEXIT;
}
- return (kern_ptrace(td, PT_SET_EVENT_MASK, pid, &mask, sizeof(mask)));
+ return (kern_ptrace(td, false, PT_SET_EVENT_MASK, pid, &mask,
+ sizeof(mask)));
}
static int
@@ -240,7 +242,8 @@
l_siginfo_t l_siginfo;
int error, sig;
- error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo));
+ error = kern_ptrace(td, false, PT_LWPINFO, pid, &lwpinfo,
+ sizeof(lwpinfo));
if (error != 0) {
linux_msg(td, "PT_LWPINFO failed with error %d", error);
return (error);
@@ -266,7 +269,7 @@
struct linux_pt_regset l_regset;
int error;
- error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0);
+ error = kern_ptrace(td, false, PT_GETREGS, pid, &b_reg, 0);
if (error != 0)
return (error);
@@ -290,7 +293,7 @@
if (error != 0)
return (error);
linux_to_bsd_regset(&b_reg, &l_regset);
- error = kern_ptrace(td, PT_SETREGS, pid, &b_reg, 0);
+ error = kern_ptrace(td, false, PT_SETREGS, pid, &b_reg, 0);
return (error);
}
@@ -309,7 +312,7 @@
return (error);
}
- error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0);
+ error = kern_ptrace(td, false, PT_GETREGS, pid, &b_reg, 0);
if (error != 0)
return (error);
@@ -351,7 +354,7 @@
return (error);
}
- error = kern_ptrace(td, PT_GETFPREGS, pid, &b_fpreg, 0);
+ error = kern_ptrace(td, false, PT_GETFPREGS, pid, &b_fpreg, 0);
if (error != 0)
return (error);
@@ -387,13 +390,15 @@
return (error);
}
- error = kern_ptrace(td, PT_GETXSTATE_INFO, pid, &info, sizeof(info));
+ error = kern_ptrace(td, false, PT_GETXSTATE_INFO, pid, &info,
+ sizeof(info));
if (error != 0)
return (error);
xstate = malloc(info.xsave_len, M_LINUX, M_WAITOK | M_ZERO);
- error = kern_ptrace(td, PT_GETXSTATE, pid, xstate, info.xsave_len);
+ error = kern_ptrace(td, false, PT_GETXSTATE, pid, xstate,
+ info.xsave_len);
if (error != 0) {
free(xstate, M_LINUX);
return (error);
@@ -454,7 +459,8 @@
struct syscall_info si;
int error;
- error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo));
+ error = kern_ptrace(td, false, PT_LWPINFO, pid, &lwpinfo,
+ sizeof(lwpinfo));
if (error != 0) {
linux_msg(td, "PT_LWPINFO failed with error %d", error);
return (error);
@@ -465,7 +471,7 @@
if (lwpinfo.pl_flags & PL_FLAG_SCE) {
si.op = LINUX_PTRACE_SYSCALL_INFO_ENTRY;
si.entry.nr = lwpinfo.pl_syscall_code;
- error = kern_ptrace(td, PTLINUX_GET_SC_ARGS, pid,
+ error = kern_ptrace(td, false, PTLINUX_GET_SC_ARGS, pid,
si.entry.args, sizeof(si.entry.args));
if (error != 0) {
linux_msg(td,
@@ -474,7 +480,8 @@
}
} else if (lwpinfo.pl_flags & PL_FLAG_SCX) {
si.op = LINUX_PTRACE_SYSCALL_INFO_EXIT;
- error = kern_ptrace(td, PT_GET_SC_RET, pid, &sr, sizeof(sr));
+ error = kern_ptrace(td, false, PT_GET_SC_RET, pid, &sr,
+ sizeof(sr));
if (error != 0) {
linux_msg(td, "PT_GET_SC_RET failed with error %d",
@@ -505,7 +512,7 @@
si.op = LINUX_PTRACE_SYSCALL_INFO_NONE;
}
- error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0);
+ error = kern_ptrace(td, false, PT_GETREGS, pid, &b_reg, 0);
if (error != 0)
return (error);
@@ -534,7 +541,7 @@
switch (uap->req) {
case LINUX_PTRACE_TRACEME:
- error = kern_ptrace(td, PT_TRACE_ME, 0, 0, 0);
+ error = kern_ptrace(td, false, PT_TRACE_ME, 0, 0, 0);
break;
case LINUX_PTRACE_PEEKTEXT:
case LINUX_PTRACE_PEEKDATA:
@@ -552,13 +559,14 @@
break;
case LINUX_PTRACE_POKETEXT:
case LINUX_PTRACE_POKEDATA:
- error = kern_ptrace(td, PT_WRITE_D, pid, addr, uap->data);
+ error = kern_ptrace(td, false, PT_WRITE_D, pid, addr,
+ uap->data);
if (error != 0)
goto out;
/*
* Linux expects this syscall to write 64 bits, not 32.
*/
- error = kern_ptrace(td, PT_WRITE_D, pid,
+ error = kern_ptrace(td, false, PT_WRITE_D, pid,
(void *)(uap->addr + 4), uap->data >> 32);
break;
case LINUX_PTRACE_POKEUSER:
@@ -568,16 +576,17 @@
error = map_signum(uap->data, &sig);
if (error != 0)
break;
- error = kern_ptrace(td, PT_CONTINUE, pid, (void *)1, sig);
+ error = kern_ptrace(td, false, PT_CONTINUE, pid, (void *)1,
+ sig);
break;
case LINUX_PTRACE_KILL:
- error = kern_ptrace(td, PT_KILL, pid, addr, uap->data);
+ error = kern_ptrace(td, false, PT_KILL, pid, addr, uap->data);
break;
case LINUX_PTRACE_SINGLESTEP:
error = map_signum(uap->data, &sig);
if (error != 0)
break;
- error = kern_ptrace(td, PT_STEP, pid, (void *)1, sig);
+ error = kern_ptrace(td, false, PT_STEP, pid, (void *)1, sig);
break;
case LINUX_PTRACE_GETREGS:
error = linux_ptrace_getregs(td, pid, (void *)uap->data);
@@ -586,19 +595,21 @@
error = linux_ptrace_setregs(td, pid, (void *)uap->data);
break;
case LINUX_PTRACE_ATTACH:
- error = kern_ptrace(td, PT_ATTACH, pid, addr, uap->data);
+ error = kern_ptrace(td, false, PT_ATTACH, pid, addr,
+ uap->data);
break;
case LINUX_PTRACE_DETACH:
error = map_signum(uap->data, &sig);
if (error != 0)
break;
- error = kern_ptrace(td, PT_DETACH, pid, (void *)1, sig);
+ error = kern_ptrace(td, false, PT_DETACH, pid, (void *)1, sig);
break;
case LINUX_PTRACE_SYSCALL:
error = map_signum(uap->data, &sig);
if (error != 0)
break;
- error = kern_ptrace(td, PT_SYSCALL, pid, (void *)1, sig);
+ error = kern_ptrace(td, false, PT_SYSCALL, pid, (void *)1,
+ sig);
break;
case LINUX_PTRACE_SETOPTIONS:
error = linux_ptrace_setoptions(td, pid, uap->data);
diff --git a/sys/i386/linux/linux_ptrace_machdep.c b/sys/i386/linux/linux_ptrace_machdep.c
--- a/sys/i386/linux/linux_ptrace_machdep.c
+++ b/sys/i386/linux/linux_ptrace_machdep.c
@@ -259,13 +259,13 @@
case PTRACE_POKETEXT:
case PTRACE_POKEDATA:
case PTRACE_KILL:
- error = kern_ptrace(td, req, pid, addr, uap->data);
+ error = kern_ptrace(td, false, req, pid, addr, uap->data);
break;
case PTRACE_PEEKTEXT:
case PTRACE_PEEKDATA: {
/* need to preserve return value */
int rval = td->td_retval[0];
- error = kern_ptrace(td, req, pid, addr, 0);
+ error = kern_ptrace(td, false, req, pid, addr, 0);
if (error == 0)
error = copyout(td->td_retval, (void *)uap->data,
sizeof(l_int));
@@ -273,20 +273,20 @@
break;
}
case PTRACE_DETACH:
- error = kern_ptrace(td, PT_DETACH, pid, (void *)1,
+ error = kern_ptrace(td, false, PT_DETACH, pid, (void *)1,
map_signum(uap->data));
break;
case PTRACE_SINGLESTEP:
case PTRACE_CONT:
- error = kern_ptrace(td, req, pid, (void *)1,
+ error = kern_ptrace(td, false, req, pid, (void *)1,
map_signum(uap->data));
break;
case PTRACE_ATTACH:
- error = kern_ptrace(td, PT_ATTACH, pid, addr, uap->data);
+ error = kern_ptrace(td, false, PT_ATTACH, pid, addr, uap->data);
break;
case PTRACE_GETREGS:
/* Linux is using data where FreeBSD is using addr */
- error = kern_ptrace(td, PT_GETREGS, pid, &u.bsd_reg, 0);
+ error = kern_ptrace(td, false, PT_GETREGS, pid, &u.bsd_reg, 0);
if (error == 0) {
map_regs_to_linux(&u.bsd_reg, &r.reg);
error = copyout(&r.reg, (void *)uap->data,
@@ -303,7 +303,8 @@
break;
case PTRACE_GETFPREGS:
/* Linux is using data where FreeBSD is using addr */
- error = kern_ptrace(td, PT_GETFPREGS, pid, &u.bsd_fpreg, 0);
+ error = kern_ptrace(td, false, PT_GETFPREGS, pid,
+ &u.bsd_fpreg, 0);
if (error == 0) {
map_fpregs_to_linux(&u.bsd_fpreg, &r.fpreg);
error = copyout(&r.fpreg, (void *)uap->data,
@@ -315,7 +316,7 @@
error = copyin((void *)uap->data, &r.fpreg, sizeof(r.fpreg));
if (error == 0) {
map_fpregs_from_linux(&u.bsd_fpreg, &r.fpreg);
- error = kern_ptrace(td, PT_SETFPREGS, pid,
+ error = kern_ptrace(td, false, PT_SETFPREGS, pid,
&u.bsd_fpreg, 0);
}
break;
@@ -409,7 +410,8 @@
* as necessary.
*/
if (uap->addr < sizeof(struct linux_pt_reg)) {
- error = kern_ptrace(td, PT_GETREGS, pid, &u.bsd_reg, 0);
+ error = kern_ptrace(td, false, PT_GETREGS, pid,
+ &u.bsd_reg, 0);
if (error != 0)
break;
@@ -424,7 +426,8 @@
(l_int)uap->data;
map_regs_from_linux(&u.bsd_reg, &r.reg);
- error = kern_ptrace(td, PT_SETREGS, pid, &u.bsd_reg, 0);
+ error = kern_ptrace(td, false; PT_SETREGS, pid,
+ &u.bsd_reg, 0);
}
/*
@@ -432,8 +435,8 @@
*/
if (uap->addr >= LINUX_DBREG_OFFSET &&
uap->addr <= LINUX_DBREG_OFFSET + LINUX_DBREG_SIZE) {
- error = kern_ptrace(td, PT_GETDBREGS, pid, &u.bsd_dbreg,
- 0);
+ error = kern_ptrace(td, false, PT_GETDBREGS, pid,
+ &u.bsd_dbreg, 0);
if (error != 0)
break;
@@ -447,7 +450,7 @@
*(l_int *)((char *)&u.bsd_dbreg + uap->addr) =
uap->data;
- error = kern_ptrace(td, PT_SETDBREGS, pid,
+ error = kern_ptrace(td, false, PT_SETDBREGS, pid,
&u.bsd_dbreg, 0);
}
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;
@@ -1066,8 +1077,10 @@
if (flags & RFPROCDESC) {
error = procdesc_falloc(td, &fp_procdesc, fr->fr_pd_fd,
fr->fr_pd_flags, fr->fr_pd_fcaps);
- if (error != 0)
+ if (error != 0) {
+ filecaps_free(fr->fr_pd_fcaps);
goto fail2;
+ }
AUDIT_ARG_FD(*fr->fr_pd_fd);
}
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>
@@ -738,6 +739,7 @@
syscallarg_t pscr_args[nitems(td->td_sa.args)];
void *addr;
int error;
+ bool pd_mode;
if (!allow_ptrace)
return (ENOSYS);
@@ -747,6 +749,9 @@
AUDIT_ARG_CMD(uap->req);
AUDIT_ARG_VALUE(uap->data);
addr = &r;
+ pd_mode = (uap->req & PT_PROCDESC) != 0;
+ uap->req &= ~PT_PROCDESC;
+
switch (uap->req) {
case PT_GET_EVENT_MASK:
case PT_LWPINFO:
@@ -835,7 +840,7 @@
if (error != 0)
return (error);
- error = kern_ptrace(td, uap->req, uap->pid, addr, uap->data);
+ error = kern_ptrace(td, pd_mode, uap->req, uap->pid, addr, uap->data);
if (error != 0)
return (error);
@@ -1055,7 +1060,8 @@
}
int
-kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
+kern_ptrace(struct thread *td, bool pd_mode, int req, int pid, void *addr,
+ int data)
{
struct iovec iov;
struct uio uio;
@@ -1069,6 +1075,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;
@@ -1080,6 +1087,7 @@
curp = td->td_proc;
proctree_locked = false;
p2_req_set = false;
+ pfp = NULL;
/* Lock proctree before locking the process. */
switch (req) {
@@ -1108,7 +1116,17 @@
p = td->td_proc;
PROC_LOCK(p);
} else {
- if (pid <= PID_MAX) {
+ if (pd_mode) {
+ if (!proctree_locked)
+ sx_slock(&proctree_lock);
+ error = fget_procdesc(td, pid, &cap_ptrace_rights,
+ &pfp, NULL, &p);
+ if (!proctree_locked)
+ sx_sunlock(&proctree_lock);
+ if (error != 0)
+ goto fail_proctree;
+ tid = pid = p->p_pid;
+ } else if (pid <= PID_MAX) {
if ((p = pfind(pid)) == NULL) {
if (proctree_locked)
sx_xunlock(&proctree_lock);
@@ -2020,8 +2038,11 @@
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
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/procdesc.h b/sys/sys/procdesc.h
--- a/sys/sys/procdesc.h
+++ b/sys/sys/procdesc.h
@@ -161,8 +161,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
@@ -36,6 +36,8 @@
#include <sys/param.h>
#include <machine/reg.h>
+#define PT_PROCDESC 0x80000000 /* pid is procdesc */
+
#define PT_TRACE_ME 0 /* child declares it's being traced */
#define PT_READ_I 1 /* read word in child's I space */
#define PT_READ_D 2 /* read word in child's D space */
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -308,8 +308,8 @@
int kern_preadv(struct thread *td, int fd, struct uio *auio, off_t offset);
int kern_pselect(struct thread *td, int nd, fd_set *in, fd_set *ou,
fd_set *ex, struct timeval *tvp, sigset_t *uset, int abi_nfdbits);
-int kern_ptrace(struct thread *td, int req, pid_t pid, void *addr,
- int data);
+int kern_ptrace(struct thread *td, bool pd_mode, int req, pid_t pid,
+ void *addr, int data);
int kern_pwrite(struct thread *td, int fd, const void *buf, size_t nbyte,
off_t offset);
int kern_pwritev(struct thread *td, int fd, struct uio *auio, off_t offset);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Aug 4, 3:25 AM (5 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35928371
Default Alt Text
D58586.diff (21 KB)
Attached To
Mode
D58586: Make ptrace(2) operating on process descriptors
Attached
Detach File
Event Timeline
Log In to Comment