Page MenuHomeFreeBSD

D30457.id89832.diff
No OneTemporary

D30457.id89832.diff

diff --git a/sys/amd64/linux/linux_ptrace.c b/sys/amd64/linux/linux_ptrace.c
--- a/sys/amd64/linux/linux_ptrace.c
+++ b/sys/amd64/linux/linux_ptrace.c
@@ -70,7 +70,9 @@
#define LINUX_PTRACE_GETSIGINFO 0x4202
#define LINUX_PTRACE_GETREGSET 0x4204
#define LINUX_PTRACE_SEIZE 0x4206
-#define LINUX_PTRACE_GET_SYSCALL_INFO 0x420e
+#define LINUX_PTRACE_INTERRUPT 0x4207
+#define LINUX_PTRACE_LISTEN 0x4208
+#define LINUX_PTRACE_GET_SYSCALL_INFO 0x420e
#define LINUX_PTRACE_EVENT_EXIT 6
@@ -577,14 +579,6 @@
}
}
-static int
-linux_ptrace_seize(struct thread *td, pid_t pid, l_ulong addr, l_ulong data)
-{
-
- linux_msg(td, "PTRACE_SEIZE not implemented; returning EINVAL");
- return (EINVAL);
-}
-
static int
linux_ptrace_get_syscall_info(struct thread *td, pid_t pid, l_ulong addr, l_ulong data)
{
@@ -701,11 +695,18 @@
error = linux_ptrace_getregset(td, pid, uap->addr, uap->data);
break;
case LINUX_PTRACE_SEIZE:
- error = linux_ptrace_seize(td, pid, uap->addr, uap->data);
+ error = linux_ptrace_setoptions(td, pid, uap->data);
+ error = kern_ptrace(td, PT_SEIZE, pid, addr, uap->data);
+ break;
+ case LINUX_PTRACE_INTERRUPT:
+ error = kern_ptrace(td, PT_INTERRUPT, pid, addr, uap->data);
break;
- case LINUX_PTRACE_GET_SYSCALL_INFO:
- error = linux_ptrace_get_syscall_info(td, pid, uap->addr, uap->data);
+ case LINUX_PTRACE_LISTEN:
+ error = kern_ptrace(td, PT_LISTEN, pid, addr, uap->data);
break;
+// case LINUX_PTRACE_GET_SYSCALL_INFO:
+// error = linux_ptrace_get_syscall_info(td, pid, uap->addr, uap->data);
+// break;
default:
linux_msg(td, "ptrace(%ld, ...) not implemented; "
"returning EINVAL", uap->req);
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -2884,6 +2884,20 @@
}
}
+
+ if ((p->p_flag & P_TRACED) != 0 &&
+ (p->p_flag2 & P2_SEIZED) != 0 &&
+ SIGISMEMBER(sigpending, SIGKILL)) {
+ /*
+ * If we are seized: linux behavior is to honor
+ * the SIGKILL request without first sending a
+ * STOP signal to the process being debugged.
+ */
+ sig = SIGKILL;
+ //proc_wkilled(p);
+ return (SIGKILL);
+ }
+
if ((p->p_flag & (P_TRACED | P_PPTRACE)) == P_TRACED &&
(p->p_flag2 & P2_PTRACE_FSTP) != 0 &&
SIGISMEMBER(sigpending, SIGSTOP)) {
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
@@ -623,6 +623,8 @@
/* Lock proctree before locking the process. */
switch (req) {
case PT_TRACE_ME:
+ case PT_INTERRUPT:
+ case PT_SEIZE:
case PT_ATTACH:
case PT_STEP:
case PT_CONTINUE:
@@ -709,6 +711,17 @@
* Permissions check
*/
switch (req) {
+ case PT_INTERRUPT:
+ case PT_LISTEN:
+ /*
+ * Only works on tracees attached by PT_SEIZE.
+ */
+ if ((p->p_flag2 & P2_SEIZED) == 0) {
+ error = EINVAL;
+ goto fail;
+ }
+ break;
+
case PT_TRACE_ME:
/*
* Always legal, when there is a parent process which
@@ -724,6 +737,7 @@
}
break;
+ case PT_SEIZE:
case PT_ATTACH:
/* Self */
if (p == td->td_proc) {
@@ -806,6 +820,52 @@
CTR1(KTR_PTRACE, "PT_TRACE_ME: pid %d", p->p_pid);
break;
+ case PT_SEIZE:
+ proc_set_traced(p, false);
+ proc_reparent(p, td->td_proc, false);
+ CTR2(KTR_PTRACE, "PT_ATTACH: pid %d, oppid %d", p->p_pid,
+ p->p_oppid);
+
+ sx_xunlock(&proctree_lock);
+ proctree_locked = false;
+ MPASS(p->p_xthread == NULL);
+ MPASS((p->p_flag & P_STOPPED_TRACE) == 0);
+
+ p->p_flag2 |= P2_SEIZED;
+
+ /*
+ * XXX Do we actually have to do anything here?
+ */
+ break;
+
+ case PT_INTERRUPT:
+ sx_xunlock(&proctree_lock);
+ proctree_locked = false;
+ MPASS(p->p_xthread == NULL);
+ MPASS((p->p_flag & P_STOPPED_TRACE) == 0);
+
+ /*
+ * If already stopped due to a stop signal, clear the
+ * existing stop before triggering a traced SIGSTOP.
+ */
+ if ((p->p_flag & P_STOPPED_SIG) != 0) {
+ PROC_SLOCK(p);
+ p->p_flag &= ~(P_STOPPED_SIG | P_WAITED);
+ thread_unsuspend(p);
+ PROC_SUNLOCK(p);
+ }
+
+ kern_psignal(p, SIGSTOP);
+ break;
+
+ case PT_LISTEN:
+ // XXX not sure
+ td2->td_dbgflags |= TDB_SUSPEND;
+ thread_lock(td2);
+ td2->td_flags |= TDF_NEEDSUSPCHK;
+ thread_unlock(td2);
+ break;
+
case PT_ATTACH:
/* security check done above */
/*
@@ -817,7 +877,7 @@
* The old parent is remembered so we can put things back
* on a "detach".
*/
- proc_set_traced(p, true);
+ proc_set_traced(p, req == PT_ATTACH);
proc_reparent(p, td->td_proc, false);
CTR2(KTR_PTRACE, "PT_ATTACH: pid %d, oppid %d", p->p_pid,
p->p_oppid);
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -813,6 +813,7 @@
MAP_STACK */
#define P2_STKGAP_DISABLE_EXEC 0x00001000 /* Stack gap disabled
after exec */
+#define P2_SEIZED 0x00008000 /* Linux behaviour 'seize'. */
/* Flags protected by proctree_lock, kept in p_treeflags. */
#define P_TREE_ORPHANED 0x00000001 /* Reparented, on orphan list */
diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h
--- a/sys/sys/ptrace.h
+++ b/sys/sys/ptrace.h
@@ -83,6 +83,9 @@
#define PT_VM_TIMESTAMP 40 /* Get VM version (timestamp) */
#define PT_VM_ENTRY 41 /* Get VM map (entry) */
+#define PT_SEIZE 42 /* like attach but do not stop */
+#define PT_INTERRUPT 43 /* */
+#define PT_LISTEN 44 /* */
#define PT_FIRSTMACH 64 /* for machine-specific requests */
#include <machine/ptrace.h> /* machine-specific requests, if any */

File Metadata

Mime Type
text/plain
Expires
Sat, Sep 12, 3:30 AM (2 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38731795
Default Alt Text
D30457.id89832.diff (5 KB)

Event Timeline