Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 18 May 2023 17:02:51 GMT
From:      Dmitry Chagin <dchagin@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: dd2a6cd701ae - main - linux(4): Make ptrace_peekusr machine dependend
Message-ID:  <202305181702.34IH2pCi018642@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by dchagin:

URL: https://cgit.FreeBSD.org/src/commit/?id=dd2a6cd701aea5a6ced59b9947e087304f7d7238

commit dd2a6cd701aea5a6ced59b9947e087304f7d7238
Author:     Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2023-05-18 17:00:12 +0000
Commit:     Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2023-05-18 17:00:12 +0000

    linux(4): Make ptrace_peekusr machine dependend
    
    And partially implement it for x86_64.
    
    Differential Revision:  https://reviews.freebsd.org/D40095
    MFC after:              1 week
---
 sys/amd64/linux/linux.h             |  2 ++
 sys/amd64/linux/linux_machdep.c     | 31 ++++++++++++++++++++++++++
 sys/amd64/linux32/linux.h           |  2 ++
 sys/amd64/linux32/linux32_machdep.c |  9 ++++++++
 sys/arm64/linux/linux.h             |  2 ++
 sys/arm64/linux/linux_machdep.c     |  8 +++++++
 sys/compat/linux/linux_ptrace.c     | 43 -------------------------------------
 7 files changed, 54 insertions(+), 43 deletions(-)

diff --git a/sys/amd64/linux/linux.h b/sys/amd64/linux/linux.h
index c15381dc1e86..698c560154ec 100644
--- a/sys/amd64/linux/linux.h
+++ b/sys/amd64/linux/linux.h
@@ -277,6 +277,8 @@ void	linux_ptrace_get_syscall_info_machdep(const struct reg *reg,
 	    struct syscall_info *si);
 int	linux_ptrace_getregs_machdep(struct thread *td, pid_t pid,
 	    struct linux_pt_regset *l_regset);
+int	linux_ptrace_peekuser(struct thread *td, pid_t pid,
+	    void *addr, void *data);
 #endif /* _KERNEL */
 
 #endif /* !_AMD64_LINUX_H_ */
diff --git a/sys/amd64/linux/linux_machdep.c b/sys/amd64/linux/linux_machdep.c
index 6c96dd496fdc..233d66a40899 100644
--- a/sys/amd64/linux/linux_machdep.c
+++ b/sys/amd64/linux/linux_machdep.c
@@ -367,3 +367,34 @@ linux_ptrace_getregs_machdep(struct thread *td, pid_t pid,
 
 	return (0);
 }
+
+#define	LINUX_URO(a,m) ((uintptr_t)a == offsetof(struct linux_pt_regset, m))
+
+int
+linux_ptrace_peekuser(struct thread *td, pid_t pid, void *addr, void *data)
+{
+	struct linux_pt_regset reg;
+	struct reg b_reg;
+	uint64_t val;
+	int error;
+
+	if ((uintptr_t)addr & (sizeof(data) -1) || (uintptr_t)addr < 0)
+		return (EIO);
+	if ((uintptr_t)addr >= sizeof(struct linux_pt_regset)) {
+		LINUX_RATELIMIT_MSG_OPT1("PTRACE_PEEKUSER offset %ld "
+		    "not implemented; returning EINVAL", (uintptr_t)addr);
+		return (EINVAL);
+	}
+
+	if (LINUX_URO(addr, fs_base))
+		return (kern_ptrace(td, PT_GETFSBASE, pid, data, 0));
+	if (LINUX_URO(addr, gs_base))
+		return (kern_ptrace(td, PT_GETGSBASE, pid, data, 0));
+	if ((error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0)) != 0)
+		return (error);
+	bsd_to_linux_regset(&b_reg, &reg);
+	val = *(&reg.r15 + ((uintptr_t)addr / sizeof(reg.r15)));
+	return (copyout(&val, data, sizeof(val)));
+}
+
+#undef LINUX_URO
diff --git a/sys/amd64/linux32/linux.h b/sys/amd64/linux32/linux.h
index 652dfccd75f1..23cba6aa2e2c 100644
--- a/sys/amd64/linux32/linux.h
+++ b/sys/amd64/linux32/linux.h
@@ -431,6 +431,8 @@ struct reg32;
 
 void	bsd_to_linux_regset32(const struct reg32 *b_reg,
 	    struct linux_pt_regset32 *l_regset);
+int	linux_ptrace_peekuser(struct thread *td, pid_t pid,
+	    void *addr, void *data);
 
 extern bool linux32_emulate_i386;
 #endif /* _KERNEL */
diff --git a/sys/amd64/linux32/linux32_machdep.c b/sys/amd64/linux32/linux32_machdep.c
index 0bd398042c3f..afc60fb7e822 100644
--- a/sys/amd64/linux32/linux32_machdep.c
+++ b/sys/amd64/linux32/linux32_machdep.c
@@ -742,3 +742,12 @@ DEFINE_IFUNC(, int, futex_xorl, (int, uint32_t *, int *))
 	return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
 	    futex_xorl_smap : futex_xorl_nosmap);
 }
+
+int
+linux_ptrace_peekuser(struct thread *td, pid_t pid, void *addr, void *data)
+{
+
+	LINUX_RATELIMIT_MSG_OPT1("PTRACE_PEEKUSER offset %ld not implemented; "
+	    "returning EINVAL", (uintptr_t)addr);
+	return (EINVAL);
+}
diff --git a/sys/arm64/linux/linux.h b/sys/arm64/linux/linux.h
index 423f1fb0acb8..9ef50bce42a5 100644
--- a/sys/arm64/linux/linux.h
+++ b/sys/arm64/linux/linux.h
@@ -204,6 +204,8 @@ void	linux_ptrace_get_syscall_info_machdep(const struct reg *reg,
 	    struct syscall_info *si);
 int	linux_ptrace_getregs_machdep(struct thread *td, pid_t pid,
 	    struct linux_pt_regset *l_regset);
+int	linux_ptrace_peekuser(struct thread *td, pid_t pid,
+	    void *addr, void *data);
 #endif /* _KERNEL */
 
 #endif /* _ARM64_LINUX_H_ */
diff --git a/sys/arm64/linux/linux_machdep.c b/sys/arm64/linux/linux_machdep.c
index 91eea2c6c5e0..2c0445bbed5d 100644
--- a/sys/arm64/linux/linux_machdep.c
+++ b/sys/arm64/linux/linux_machdep.c
@@ -152,3 +152,11 @@ linux_ptrace_getregs_machdep(struct thread *td __unused, pid_t pid __unused,
 	return (0);
 }
 
+int
+linux_ptrace_peekuser(struct thread *td, pid_t pid, void *addr, void *data)
+{
+
+	LINUX_RATELIMIT_MSG_OPT1("PTRACE_PEEKUSER offset %ld not implemented; "
+	    "returning EINVAL", (uintptr_t)addr);
+	return (EINVAL);
+}
diff --git a/sys/compat/linux/linux_ptrace.c b/sys/compat/linux/linux_ptrace.c
index 75b616b7258a..bc595ce106dc 100644
--- a/sys/compat/linux/linux_ptrace.c
+++ b/sys/compat/linux/linux_ptrace.c
@@ -100,11 +100,6 @@ __FBSDID("$FreeBSD$");
 #define	LINUX_PTRACE_SYSCALL_INFO_ENTRY	1
 #define	LINUX_PTRACE_SYSCALL_INFO_EXIT	2
 
-#define LINUX_PTRACE_PEEKUSER_ORIG_RAX	120
-#define LINUX_PTRACE_PEEKUSER_RIP	128
-#define LINUX_PTRACE_PEEKUSER_CS	136
-#define LINUX_PTRACE_PEEKUSER_DS	184
-
 static int
 map_signum(int lsig, int *bsigp)
 {
@@ -179,44 +174,6 @@ linux_ptrace_peek(struct thread *td, pid_t pid, void *addr, void *data)
 	return (error);
 }
 
-static int
-linux_ptrace_peekuser(struct thread *td, pid_t pid, void *addr, void *data)
-{
-	struct reg b_reg;
-	uint64_t val;
-	int error;
-
-	error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0);
-	if (error != 0)
-		return (error);
-
-	switch ((uintptr_t)addr) {
-#ifdef __amd64__
-	case LINUX_PTRACE_PEEKUSER_ORIG_RAX:
-		val = b_reg.r_rax;
-		break;
-	case LINUX_PTRACE_PEEKUSER_RIP:
-		val = b_reg.r_rip;
-		break;
-	case LINUX_PTRACE_PEEKUSER_CS:
-		val = b_reg.r_cs;
-		break;
-	case LINUX_PTRACE_PEEKUSER_DS:
-		val = b_reg.r_ds;
-		break;
-#endif /* __amd64__ */
-	default:
-		linux_msg(td, "PTRACE_PEEKUSER offset %ld not implemented; "
-		    "returning EINVAL", (uintptr_t)addr);
-		return (EINVAL);
-	}
-
-	error = copyout(&val, data, sizeof(val));
-	td->td_retval[0] = error;
-
-	return (error);
-}
-
 static int
 linux_ptrace_pokeuser(struct thread *td, pid_t pid, void *addr, void *data)
 {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202305181702.34IH2pCi018642>