Page MenuHomeFreeBSD

D58586.diff
No OneTemporary

D58586.diff

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, &reg);
val = *(&reg.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, &reg);
*(&reg.r15 + ((uintptr_t)addr / sizeof(reg.r15))) = (uint64_t)data;
linux_to_bsd_regset(&b_reg1, &reg);
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

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)

Event Timeline