Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F168351419
D58586.id184258.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D58586.id184258.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/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,12 @@
.It Dv CAP_PDKILL
Permit
.Xr pdkill 2 .
+.It Dv CAP_PTRACE
+Permit debugging using
+.Xr ptrace 2
+requests with the
+.Dv PT_PROCDESC
+modifier.
.It Dv CAP_PDWAIT
Permit
.Xr pdwait 2 .
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,8 @@
if (error)
return (error);
- error = kern_ptrace(td, uap->req, uap->pid, addr, data);
+ error = (pd_mode ? kern_pdptrace : kern_ptrace)(td, uap->req,
+ uap->pid, addr, data);
if (error)
return (error);
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;
@@ -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>
@@ -739,6 +740,7 @@
syscallarg_t pscr_args[nitems(td->td_sa.args)];
void *addr;
int error;
+ bool pd_mode;
if (!allow_ptrace)
return (ENOSYS);
@@ -748,6 +750,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:
@@ -836,7 +841,8 @@
if (error != 0)
return (error);
- error = kern_ptrace(td, uap->req, uap->pid, addr, uap->data);
+ error = (pd_mode ? kern_pdptrace : kern_ptrace)(td, uap->req,
+ uap->pid, addr, uap->data);
if (error != 0)
return (error);
@@ -1055,8 +1061,9 @@
return (NULL);
}
-int
-kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
+static int
+ptraceimpl(struct thread *td, int req, bool pd_mode, int pid, void *addr,
+ int data)
{
struct iovec iov;
struct uio uio;
@@ -1070,6 +1077,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 +1089,7 @@
curp = td->td_proc;
proctree_locked = false;
p2_req_set = false;
+ pfp = NULL;
/* Lock proctree before locking the process. */
switch (req) {
@@ -1108,24 +1117,30 @@
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 {
- td2 = tdfind(pid, -1);
- if (td2 == NULL) {
- if (proctree_locked)
- sx_xunlock(&proctree_lock);
- return (ESRCH);
- }
- p = td2->td_proc;
- tid = pid;
- pid = p->p_pid;
+ } else if (pd_mode) {
+ if (!proctree_locked)
+ sx_slock(&proctree_lock);
+ error = fget_procdesc(td, pid, &cap_ptrace_rights, EINVAL,
+ &pfp, NULL, &p);
+ if (!proctree_locked)
+ sx_sunlock(&proctree_lock);
+ if (error != 0)
+ goto fail_proctree;
+ pid = p->p_pid;
+ } 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 +2036,24 @@
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_pdptrace(struct thread *td, int req, int pfd, void *addr, int data)
+{
+ return (ptraceimpl(td, req, true, pfd, addr, data));
+}
+
+int
+kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
+{
+ return (ptraceimpl(td, req, false, pid, addr, data));
+}
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
@@ -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
@@ -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,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Aug 28, 6:00 PM (9 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37473765
Default Alt Text
D58586.id184258.diff (12 KB)
Attached To
Mode
D58586: pdptrace(2)
Attached
Detach File
Event Timeline
Log In to Comment