svn commit: r364505 - in stable/12/sys: amd64/linux compat/linux

Edward Tomasz Napierala trasz at FreeBSD.org
Sun Aug 23 19:22:43 UTC 2020


Author: trasz
Date: Sun Aug 23 19:22:42 2020
New Revision: 364505
URL: https://svnweb.freebsd.org/changeset/base/364505

Log:
  MFC r347971:
  
  Implement PTRACE_O_TRACESYSGOOD.  This makes Linux strace(1) work.
  
  Sponsored by:	The FreeBSD Foundation

Modified:
  stable/12/sys/amd64/linux/linux_ptrace.c
  stable/12/sys/compat/linux/linux_emul.h
  stable/12/sys/compat/linux/linux_misc.c
  stable/12/sys/compat/linux/linux_misc.h
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/amd64/linux/linux_ptrace.c
==============================================================================
--- stable/12/sys/amd64/linux/linux_ptrace.c	Sun Aug 23 19:20:38 2020	(r364504)
+++ stable/12/sys/amd64/linux/linux_ptrace.c	Sun Aug 23 19:22:42 2020	(r364505)
@@ -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 *
 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, 
 		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;

Modified: stable/12/sys/compat/linux/linux_emul.h
==============================================================================
--- stable/12/sys/compat/linux/linux_emul.h	Sun Aug 23 19:20:38 2020	(r364504)
+++ stable/12/sys/compat/linux/linux_emul.h	Sun Aug 23 19:22:42 2020	(r364505)
@@ -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)

Modified: stable/12/sys/compat/linux/linux_misc.c
==============================================================================
--- stable/12/sys/compat/linux/linux_misc.c	Sun Aug 23 19:20:38 2020	(r364504)
+++ stable/12/sys/compat/linux/linux_misc.c	Sun Aug 23 19:22:42 2020	(r364505)
@@ -984,27 +984,53 @@ linux_futimesat(struct thread *td, struct linux_futime
 }
 #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);
@@ -1035,7 +1061,7 @@ int
 linux_wait4(struct thread *td, struct linux_wait4_args *args)
 {
 	int error, options;
-	struct rusage ru, *rup;
+	struct __wrusage wru, *wrup;
 
 #ifdef DEBUG
 	if (ldebug(wait4))
@@ -1051,14 +1077,14 @@ linux_wait4(struct thread *td, struct linux_wait4_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);
 }
 

Modified: stable/12/sys/compat/linux/linux_misc.h
==============================================================================
--- stable/12/sys/compat/linux/linux_misc.h	Sun Aug 23 19:20:38 2020	(r364504)
+++ stable/12/sys/compat/linux/linux_misc.h	Sun Aug 23 19:22:42 2020	(r364505)
@@ -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);


More information about the svn-src-all mailing list