The branch stable/13 has been updated by dchagin:

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

commit 9480640957ff48c6bc7c0ea5d4f3eb5930f417e3
Author:     Dmitry Chagin <[email protected]>
AuthorDate: 2023-05-18 17:00:12 +0000
Commit:     Dmitry Chagin <[email protected]>
CommitDate: 2023-06-29 08:15:59 +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
    
    (cherry picked from commit dd2a6cd701aea5a6ced59b9947e087304f7d7238)
---
 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 a5682c6a980d..57f1ee0115e6 100644
--- a/sys/amd64/linux/linux.h
+++ b/sys/amd64/linux/linux.h
@@ -322,6 +322,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 32f2f42b0108..a98777adeaf5 100644
--- a/sys/amd64/linux32/linux.h
+++ b/sys/amd64/linux32/linux.h
@@ -465,6 +465,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 5a391c3543d3..be6733c81d97 100644
--- a/sys/arm64/linux/linux.h
+++ b/sys/arm64/linux/linux.h
@@ -238,6 +238,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 4b12476f7865..2e472869eedb 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 151355d2bb3f..c1c7abf70a9d 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)
 {

Reply via email to