Page MenuHomeFreeBSD

D28212.id91817.diff
No OneTemporary

D28212.id91817.diff

Index: sys/amd64/linux/linux_ptrace.c
===================================================================
--- sys/amd64/linux/linux_ptrace.c
+++ sys/amd64/linux/linux_ptrace.c
@@ -94,6 +94,12 @@
LINUX_PTRACE_O_TRACESECCOMP | LINUX_PTRACE_O_EXITKILL | \
LINUX_PTRACE_O_SUSPEND_SECCOMP)
+#define LINUX_PTRACE_SYSCALL_INFO_NONE 0
+#define LINUX_PTRACE_SYSCALL_INFO_ENTRY 1
+#define LINUX_PTRACE_SYSCALL_INFO_EXIT 2
+
+#define LINUX_ARCH_AMD64 0xc000003e
+
static int
map_signum(int lsig, int *bsigp)
{
@@ -173,6 +179,28 @@
l_ulong ss;
};
+struct syscall_info {
+ uint8_t op;
+ uint32_t arch;
+ uint64_t instruction_pointer;
+ uint64_t stack_pointer;
+ union {
+ struct {
+ uint64_t nr;
+ uint64_t args[6];
+ } entry;
+ struct {
+ int64_t rval;
+ uint8_t is_error;
+ } exit;
+ struct {
+ uint64_t nr;
+ uint64_t args[6];
+ uint32_t ret_data;
+ } seccomp;
+ };
+};
+
/*
* Translate amd64 ptrace registers between Linux and FreeBSD formats.
* The translation is pretty straighforward, for all registers but
@@ -496,11 +524,75 @@
}
static int
-linux_ptrace_get_syscall_info(struct thread *td, pid_t pid, l_ulong addr, l_ulong data)
+linux_ptrace_get_syscall_info(struct thread *td, pid_t pid,
+ l_ulong addr, l_ulong data)
{
+ struct ptrace_lwpinfo lwpinfo;
+ struct ptrace_sc_ret sr;
+ struct reg b_reg;
+ struct syscall_info si;
+ int error;
- linux_msg(td, "PTRACE_GET_SYSCALL_INFO not implemented; returning EINVAL");
- return (EINVAL);
+ error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo));
+ if (error != 0) {
+ linux_msg(td, "PT_LWPINFO failed with error %d", error);
+ return (error);
+ }
+
+ memset(&si, 0, sizeof(si));
+
+ if (lwpinfo.pl_flags & PL_FLAG_SCE) {
+ si.op = LINUX_PTRACE_SYSCALL_INFO_ENTRY;
+ si.entry.nr = lwpinfo.pl_syscall_code;
+ /*
+ * The reason for using PT_GET_SC_ARGS_ALL instead
+ * of PT_GET_SC_ARGS is to emulate Linux bug which strace(1)
+ * depends on: at initialization it tests whether ptrace works
+ * by calling close(2), or some other single-argument syscall,
+ * _with six arguments_, and then verifies whether it can
+ * fetch them all using this API; otherwise it bails out.
+ */
+ error = kern_ptrace(td, PT_GET_SC_ARGS_ALL, pid,
+ &si.entry.args, sizeof(si.entry.args));
+ if (error != 0) {
+ linux_msg(td, "PT_GET_SC_ARGS_ALL failed with error %d",
+ error);
+ return (error);
+ }
+ } 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));
+
+ if (error != 0) {
+ linux_msg(td, "PT_GET_SC_RET failed with error %d",
+ error);
+ return (error);
+ }
+
+ if (sr.sr_error == 0) {
+ si.exit.rval = sr.sr_retval[0];
+ si.exit.is_error = 0;
+ } else {
+ si.exit.rval = bsd_to_linux_errno(sr.sr_error);
+ si.exit.is_error = 1;
+ }
+ } else {
+ si.op = LINUX_PTRACE_SYSCALL_INFO_NONE;
+ }
+
+ error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0);
+ if (error != 0)
+ return (error);
+
+ si.arch = LINUX_ARCH_AMD64;
+ si.instruction_pointer = b_reg.r_rip;
+ si.stack_pointer = b_reg.r_rsp;
+
+ error = copyout(&si, (void *)data, sizeof(si));
+ if (error == 0)
+ td->td_retval[0] = sizeof(si);
+
+ return (error);
}
int
Index: sys/kern/sys_process.c
===================================================================
--- sys/kern/sys_process.c
+++ sys/kern/sys_process.c
@@ -490,6 +490,7 @@
case PT_GET_EVENT_MASK:
case PT_LWPINFO:
case PT_GET_SC_ARGS:
+ case PT_GET_SC_ARGS_ALL:
case PT_GET_SC_RET:
break;
case PT_GETREGS:
@@ -564,6 +565,7 @@
error = copyout(&r.pl, uap->addr, uap->data);
break;
case PT_GET_SC_ARGS:
+ case PT_GET_SC_ARGS_ALL:
error = copyout(r.args, uap->addr, MIN(uap->data,
sizeof(r.args)));
break;
@@ -709,6 +711,7 @@
case PT_SET_EVENT_MASK:
case PT_DETACH:
case PT_GET_SC_ARGS:
+ case PT_GET_SC_ARGS_ALL:
sx_xlock(&proctree_lock);
proctree_locked = true;
break;
@@ -1012,6 +1015,19 @@
sizeof(register_t));
break;
+ case PT_GET_SC_ARGS_ALL:
+ CTR1(KTR_PTRACE, "PT_GET_SC_ARGS_ALL: pid %d", p->p_pid);
+ if ((td2->td_dbgflags & (TDB_SCE | TDB_SCX)) == 0
+#ifdef COMPAT_FREEBSD32
+ || (wrap32 && !safe)
+#endif
+ ) {
+ error = EINVAL;
+ break;
+ }
+ bcopy(td2->td_sa.args, addr, sizeof(td2->td_sa.args));
+ break;
+
case PT_GET_SC_RET:
if ((td2->td_dbgflags & (TDB_SCX)) == 0
#ifdef COMPAT_FREEBSD32
Index: sys/sys/ptrace.h
===================================================================
--- sys/sys/ptrace.h
+++ sys/sys/ptrace.h
@@ -86,6 +86,8 @@
#define PT_VM_TIMESTAMP 40 /* Get VM version (timestamp) */
#define PT_VM_ENTRY 41 /* Get VM map (entry) */
+#define PT_GET_SC_ARGS_ALL 42 /* Used by linux(4) */
+
#define PT_FIRSTMACH 64 /* for machine-specific requests */
#include <machine/ptrace.h> /* machine-specific requests, if any */

File Metadata

Mime Type
text/plain
Expires
Fri, Oct 24, 4:01 PM (7 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24136616
Default Alt Text
D28212.id91817.diff (4 KB)

Event Timeline