summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Tomasz Napierala <trasz@FreeBSD.org>2019-05-19 12:58:44 +0000
committerEdward Tomasz Napierala <trasz@FreeBSD.org>2019-05-19 12:58:44 +0000
commitd49fb289c8ff64b175b043f25142936adfd9f5d3 (patch)
treebc3d9b8a3cd173ed337489fd7e9af05907a1c658
parentaa28871254bb18f2ea4f2b4ec087cf729b12735e (diff)
Notes
-rw-r--r--sys/amd64/linux/linux_ptrace.c47
-rw-r--r--sys/compat/linux/linux_emul.h3
-rw-r--r--sys/compat/linux/linux_misc.c58
-rw-r--r--sys/compat/linux/linux_misc.h5
4 files changed, 92 insertions, 21 deletions
diff --git a/sys/amd64/linux/linux_ptrace.c b/sys/amd64/linux/linux_ptrace.c
index ba1a64350c0ed..e4b83ba1aee26 100644
--- a/sys/amd64/linux/linux_ptrace.c
+++ b/sys/amd64/linux/linux_ptrace.c
@@ -34,8 +34,10 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/lock.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
+#include <sys/sx.h>
#include <sys/syscallsubr.h>
#include <machine/pcb.h>
@@ -43,6 +45,8 @@ __FBSDID("$FreeBSD$");
#include <amd64/linux/linux.h>
#include <amd64/linux/linux_proto.h>
+#include <compat/linux/linux_emul.h>
+#include <compat/linux/linux_misc.h>
#include <compat/linux/linux_signal.h>
#define LINUX_PTRACE_TRACEME 0
@@ -107,6 +111,37 @@ map_signum(int lsig, int *bsigp)
return (0);
}
+int
+linux_ptrace_status(struct thread *td, pid_t pid, int status)
+{
+ struct ptrace_lwpinfo lwpinfo;
+ struct linux_pemuldata *pem;
+ register_t saved_retval;
+ int error;
+
+ saved_retval = td->td_retval[0];
+ error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo));
+ td->td_retval[0] = saved_retval;
+ if (error != 0) {
+ printf("%s: PT_LWPINFO failed with error %d\n", __func__, error);
+ return (status);
+ }
+
+ pem = pem_find(td->td_proc);
+ KASSERT(pem != NULL, ("%s: proc emuldata not found.\n", __func__));
+
+ LINUX_PEM_SLOCK(pem);
+ if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACESYSGOOD) &&
+ lwpinfo.pl_flags & PL_FLAG_SCE)
+ status |= (LINUX_SIGTRAP | 0x80) << 8;
+ if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACESYSGOOD) &&
+ lwpinfo.pl_flags & PL_FLAG_SCX)
+ status |= (LINUX_SIGTRAP | 0x80) << 8;
+ LINUX_PEM_SUNLOCK(pem);
+
+ return (status);
+}
+
struct linux_pt_reg {
l_ulong r15;
l_ulong r14;
@@ -279,6 +314,7 @@ linux_ptrace_peek(struct thread *td, pid_t pid, void *addr, void *data)
static int
linux_ptrace_setoptions(struct thread *td, pid_t pid, l_ulong data)
{
+ struct linux_pemuldata *pem;
int mask;
mask = 0;
@@ -290,15 +326,20 @@ linux_ptrace_setoptions(struct thread *td, pid_t pid, l_ulong data)
return (EINVAL);
}
+ pem = pem_find(td->td_proc);
+ KASSERT(pem != NULL, ("%s: proc emuldata not found.\n", __func__));
+
/*
* PTRACE_O_EXITKILL is ignored, we do that by default.
*/
+ LINUX_PEM_XLOCK(pem);
if (data & LINUX_PTRACE_O_TRACESYSGOOD) {
- printf("%s: PTRACE_O_TRACESYSGOOD not implemented; "
- "returning EINVAL\n", __func__);
- return (EINVAL);
+ pem->ptrace_flags |= LINUX_PTRACE_O_TRACESYSGOOD;
+ } else {
+ pem->ptrace_flags &= ~LINUX_PTRACE_O_TRACESYSGOOD;
}
+ LINUX_PEM_XUNLOCK(pem);
if (data & LINUX_PTRACE_O_TRACEFORK)
mask |= PTRACE_FORK;
diff --git a/sys/compat/linux/linux_emul.h b/sys/compat/linux/linux_emul.h
index fb445de5db98b..daa92e15b5025 100644
--- a/sys/compat/linux/linux_emul.h
+++ b/sys/compat/linux/linux_emul.h
@@ -32,6 +32,8 @@
#ifndef _LINUX_EMUL_H_
#define _LINUX_EMUL_H_
+struct image_params;
+
/*
* modeled after similar structure in NetBSD
* this will be extended as we need more functionality
@@ -68,6 +70,7 @@ struct linux_pemuldata {
struct sx pem_sx; /* lock for this struct */
void *epoll; /* epoll data */
uint32_t persona; /* process execution domain */
+ uint32_t ptrace_flags; /* used by ptrace(2) */
};
#define LINUX_PEM_XLOCK(p) sx_xlock(&(p)->pem_sx)
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index a5e1260c86a02..0fe4f039c2165 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -886,27 +886,53 @@ linux_futimesat(struct thread *td, struct linux_futimesat_args *args)
}
#endif
-int
-linux_common_wait(struct thread *td, int pid, int *status,
- int options, struct rusage *ru)
+static int
+linux_common_wait(struct thread *td, int pid, int *statusp,
+ int options, struct __wrusage *wrup)
{
- int error, tmpstat;
+ siginfo_t siginfo;
+ idtype_t idtype;
+ id_t id;
+ int error, status, tmpstat;
- error = kern_wait(td, pid, &tmpstat, options, ru);
+ if (pid == WAIT_ANY) {
+ idtype = P_ALL;
+ id = 0;
+ } else if (pid < 0) {
+ idtype = P_PGID;
+ id = (id_t)-pid;
+ } else {
+ idtype = P_PID;
+ id = (id_t)pid;
+ }
+
+ /*
+ * For backward compatibility we implicitly add flags WEXITED
+ * and WTRAPPED here.
+ */
+ options |= WEXITED | WTRAPPED;
+ error = kern_wait6(td, idtype, id, &status, options, wrup, &siginfo);
if (error)
return (error);
- if (status) {
- tmpstat &= 0xffff;
- if (WIFSIGNALED(tmpstat))
+ if (statusp) {
+ tmpstat = status & 0xffff;
+ if (WIFSIGNALED(tmpstat)) {
tmpstat = (tmpstat & 0xffffff80) |
bsd_to_linux_signal(WTERMSIG(tmpstat));
- else if (WIFSTOPPED(tmpstat))
+ } else if (WIFSTOPPED(tmpstat)) {
tmpstat = (tmpstat & 0xffff00ff) |
(bsd_to_linux_signal(WSTOPSIG(tmpstat)) << 8);
- else if (WIFCONTINUED(tmpstat))
+#if defined(__amd64__) && !defined(COMPAT_LINUX32)
+ if (WSTOPSIG(status) == SIGTRAP) {
+ tmpstat = linux_ptrace_status(td,
+ siginfo.si_pid, tmpstat);
+ }
+#endif
+ } else if (WIFCONTINUED(tmpstat)) {
tmpstat = 0xffff;
- error = copyout(&tmpstat, status, sizeof(int));
+ }
+ error = copyout(&tmpstat, statusp, sizeof(int));
}
return (error);
@@ -931,7 +957,7 @@ int
linux_wait4(struct thread *td, struct linux_wait4_args *args)
{
int error, options;
- struct rusage ru, *rup;
+ struct __wrusage wru, *wrup;
if (args->options & ~(LINUX_WUNTRACED | LINUX_WNOHANG |
LINUX_WCONTINUED | __WCLONE | __WNOTHREAD | __WALL))
@@ -941,14 +967,14 @@ linux_wait4(struct thread *td, struct linux_wait4_args *args)
linux_to_bsd_waitopts(args->options, &options);
if (args->rusage != NULL)
- rup = &ru;
+ wrup = &wru;
else
- rup = NULL;
- error = linux_common_wait(td, args->pid, args->status, options, rup);
+ wrup = NULL;
+ error = linux_common_wait(td, args->pid, args->status, options, wrup);
if (error != 0)
return (error);
if (args->rusage != NULL)
- error = linux_copyout_rusage(&ru, args->rusage);
+ error = linux_copyout_rusage(&wru.wru_self, args->rusage);
return (error);
}
diff --git a/sys/compat/linux/linux_misc.h b/sys/compat/linux/linux_misc.h
index 8c003cac5a77d..f56b64a894642 100644
--- a/sys/compat/linux/linux_misc.h
+++ b/sys/compat/linux/linux_misc.h
@@ -149,8 +149,9 @@ extern int stclohz;
#define LINUX_GRND_NONBLOCK 0x0001
#define LINUX_GRND_RANDOM 0x0002
-int linux_common_wait(struct thread *td, int pid, int *status,
- int options, struct rusage *ru);
+#if defined(__amd64__) && !defined(COMPAT_LINUX32)
+int linux_ptrace_status(struct thread *td, int pid, int status);
+#endif
void linux_to_bsd_waitopts(int options, int *bsdopts);
int linux_set_upcall_kse(struct thread *td, register_t stack);
int linux_set_cloned_tls(struct thread *td, void *desc);