The orig_a0 is missing in struct user_regs_struct of riscv, and there is no way to add it without breaking UAPI. (See Link tag below)
Like NT_ARM_SYSTEM_CALL do, we add a new regset name NT_RISCV_ORIG_A0 to access original a0 register from userspace via ptrace API.
Link: https://lore.kernel.org/all/59505464-c84a-403d-972f-d4b2055eeaac@gmail.com/
Signed-off-by: Celeste Liu uwu@coelacanthus.name --- Changes in v4: - Fix a copy paste error in selftest. (Forget to commit...) - Link to v3: https://lore.kernel.org/r/20241226-riscv-new-regset-v3-0-f5b96465826b@coelac...
Changes in v3: - Use return 0 directly for readability. - Fix test for modify a0. - Add Fixes: tag - Remove useless Cc: stable. - Selftest will check both a0 and orig_a0, but depends on the correctness of PTRACE_GET_SYSCALL_INFO. - Link to v2: https://lore.kernel.org/r/20241203-riscv-new-regset-v2-0-d37da8c0cba6@coelac...
Changes in v2: - Fix integer width. - Add selftest. - Link to v1: https://lore.kernel.org/r/20241201-riscv-new-regset-v1-1-c83c58abcc7b@coelac...
--- Celeste Liu (2): riscv/ptrace: add new regset to access original a0 register riscv: selftests: Add a ptrace test to verify syscall parameter modification
arch/riscv/kernel/ptrace.c | 32 ++++++ include/uapi/linux/elf.h | 1 + tools/testing/selftests/riscv/abi/.gitignore | 1 + tools/testing/selftests/riscv/abi/Makefile | 5 +- tools/testing/selftests/riscv/abi/ptrace.c | 151 +++++++++++++++++++++++++++ 5 files changed, 189 insertions(+), 1 deletion(-) --- base-commit: 0e287d31b62bb53ad81d5e59778384a40f8b6f56 change-id: 20241201-riscv-new-regset-d529b952ad0d
Best regards,
The orig_a0 is missing in struct user_regs_struct of riscv, and there is no way to add it without breaking UAPI. (See Link tag below)
Like NT_ARM_SYSTEM_CALL do, we add a new regset name NT_RISCV_ORIG_A0 to access original a0 register from userspace via ptrace API.
Fixes: e2c0cdfba7f6 ("RISC-V: User-facing API") Link: https://lore.kernel.org/all/59505464-c84a-403d-972f-d4b2055eeaac@gmail.com/ Cc: stable@vger.kernel.org Reviewed-by: Björn Töpel bjorn@rivosinc.com Signed-off-by: Celeste Liu uwu@coelacanthus.name --- arch/riscv/kernel/ptrace.c | 32 ++++++++++++++++++++++++++++++++ include/uapi/linux/elf.h | 1 + 2 files changed, 33 insertions(+)
diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c index ea67e9fb7a583683b922fe2c017ea61f3bc848db..ef9ab74c8575a5c440155973b1c625c06a867c97 100644 --- a/arch/riscv/kernel/ptrace.c +++ b/arch/riscv/kernel/ptrace.c @@ -31,6 +31,7 @@ enum riscv_regset { #ifdef CONFIG_RISCV_ISA_SUPM REGSET_TAGGED_ADDR_CTRL, #endif + REGSET_ORIG_A0, };
static int riscv_gpr_get(struct task_struct *target, @@ -184,6 +185,29 @@ static int tagged_addr_ctrl_set(struct task_struct *target, } #endif
+static int riscv_orig_a0_get(struct task_struct *target, + const struct user_regset *regset, + struct membuf to) +{ + return membuf_store(&to, task_pt_regs(target)->orig_a0); +} + +static int riscv_orig_a0_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + unsigned long orig_a0 = task_pt_regs(target)->orig_a0; + int ret; + + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &orig_a0, 0, -1); + if (ret) + return ret; + + task_pt_regs(target)->orig_a0 = orig_a0; + return 0; +} + static const struct user_regset riscv_user_regset[] = { [REGSET_X] = { .core_note_type = NT_PRSTATUS, @@ -224,6 +248,14 @@ static const struct user_regset riscv_user_regset[] = { .set = tagged_addr_ctrl_set, }, #endif + [REGSET_ORIG_A0] = { + .core_note_type = NT_RISCV_ORIG_A0, + .n = 1, + .size = sizeof(elf_greg_t), + .align = sizeof(elf_greg_t), + .regset_get = riscv_orig_a0_get, + .set = riscv_orig_a0_set, + }, };
static const struct user_regset_view riscv_user_native_view = { diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h index b44069d29cecc0f9de90ee66bfffd2137f4275a8..390060229601631da2fb27030d9fa2142e676c14 100644 --- a/include/uapi/linux/elf.h +++ b/include/uapi/linux/elf.h @@ -452,6 +452,7 @@ typedef struct elf64_shdr { #define NT_RISCV_CSR 0x900 /* RISC-V Control and Status Registers */ #define NT_RISCV_VECTOR 0x901 /* RISC-V vector registers */ #define NT_RISCV_TAGGED_ADDR_CTRL 0x902 /* RISC-V tagged address control (prctl()) */ +#define NT_RISCV_ORIG_A0 0x903 /* RISC-V original a0 register */ #define NT_LOONGARCH_CPUCFG 0xa00 /* LoongArch CPU config registers */ #define NT_LOONGARCH_CSR 0xa01 /* LoongArch control and status registers */ #define NT_LOONGARCH_LSX 0xa02 /* LoongArch Loongson SIMD Extension registers */
This test checks that orig_a0 allows a syscall argument to be modified, and that changing a0 does not change the syscall argument.
Co-developed-by: Quan Zhou zhouquan@iscas.ac.cn Signed-off-by: Quan Zhou zhouquan@iscas.ac.cn Co-developed-by: Charlie Jenkins charlie@rivosinc.com Signed-off-by: Charlie Jenkins charlie@rivosinc.com Reviewed-by: Björn Töpel bjorn@rivosinc.com Signed-off-by: Celeste Liu uwu@coelacanthus.name --- tools/testing/selftests/riscv/abi/.gitignore | 1 + tools/testing/selftests/riscv/abi/Makefile | 5 +- tools/testing/selftests/riscv/abi/ptrace.c | 151 +++++++++++++++++++++++++++ 3 files changed, 156 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/riscv/abi/.gitignore b/tools/testing/selftests/riscv/abi/.gitignore index b38358f91c4d2240ae64892871d9ca98bda1ae58..378c605919a3b3d58eec2701eb7af430cfe315d6 100644 --- a/tools/testing/selftests/riscv/abi/.gitignore +++ b/tools/testing/selftests/riscv/abi/.gitignore @@ -1 +1,2 @@ pointer_masking +ptrace diff --git a/tools/testing/selftests/riscv/abi/Makefile b/tools/testing/selftests/riscv/abi/Makefile index ed82ff9c664e7eb3f760cbab81fb957ff72579c5..3f74d059dfdcbce4d45d8ff618781ccea1419061 100644 --- a/tools/testing/selftests/riscv/abi/Makefile +++ b/tools/testing/selftests/riscv/abi/Makefile @@ -2,9 +2,12 @@
CFLAGS += -I$(top_srcdir)/tools/include
-TEST_GEN_PROGS := pointer_masking +TEST_GEN_PROGS := pointer_masking ptrace
include ../../lib.mk
$(OUTPUT)/pointer_masking: pointer_masking.c $(CC) -static -o$@ $(CFLAGS) $(LDFLAGS) $^ + +$(OUTPUT)/ptrace: ptrace.c + $(CC) -static -o$@ $(CFLAGS) $(LDFLAGS) $^ diff --git a/tools/testing/selftests/riscv/abi/ptrace.c b/tools/testing/selftests/riscv/abi/ptrace.c new file mode 100644 index 0000000000000000000000000000000000000000..023695352215bb5de3f91c1a6f5ea3b4f9373ff9 --- /dev/null +++ b/tools/testing/selftests/riscv/abi/ptrace.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <signal.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/ptrace.h> +#include <sys/stat.h> +#include <sys/user.h> +#include <sys/wait.h> +#include <sys/uio.h> +#include <linux/elf.h> +#include <linux/unistd.h> +#include <linux/ptrace.h> +#include <asm/ptrace.h> + +#include "../../kselftest_harness.h" + +#define ORIG_A0_MODIFY 0x01 +#define A0_MODIFY 0x02 +#define A0_OLD 0x03 +#define A0_NEW 0x04 + +struct a0_regs { + __s64 orig_a0; + __u64 a0; +}; + +#define perr_and_exit(fmt, ...) \ + ({ \ + char buf[256]; \ + snprintf(buf, sizeof(buf), "%s:%d:" fmt ": %m\n", \ + __func__, __LINE__, ##__VA_ARGS__); \ + ksft_exit_fail_perror(buf); \ + }) + +static inline void resume_and_wait_tracee(pid_t pid, int flag) +{ + int status; + + if (ptrace(flag, pid, 0, 0)) + perr_and_exit("failed to resume the tracee %d\n", pid); + + if (waitpid(pid, &status, 0) != pid) + perr_and_exit("failed to wait for the tracee %d\n", pid); +} + +static void ptrace_test(int opt, struct a0_regs *result) +{ + int status; + pid_t pid; + struct user_regs_struct regs; + struct iovec iov = { + .iov_base = ®s, + .iov_len = sizeof(regs), + }; + + unsigned long orig_a0; + struct iovec a0_iov = { + .iov_base = &orig_a0, + .iov_len = sizeof(orig_a0), + }; + struct ptrace_syscall_info syscall_info_entry, syscall_info_exit; + + pid = fork(); + if (pid == 0) { + /* Mark oneself being traced */ + long val = ptrace(PTRACE_TRACEME, 0, 0, 0); + + if (val) + perr_and_exit("failed to request for tracer to trace me: %ld\n", val); + + kill(getpid(), SIGSTOP); + + /* Perform exit syscall that will be intercepted */ + exit(A0_OLD); + } + + if (pid < 0) + ksft_exit_fail_perror("failed to fork"); + + if (waitpid(pid, &status, 0) != pid) + perr_and_exit("failed to wait for the tracee %d\n", pid); + + /* Stop at the entry point of the syscall */ + resume_and_wait_tracee(pid, PTRACE_SYSCALL); + + /* Check tracee regs before the syscall */ + if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov)) + perr_and_exit("failed to get tracee registers\n"); + if (ptrace(PTRACE_GETREGSET, pid, NT_RISCV_ORIG_A0, &a0_iov)) + perr_and_exit("failed to get tracee registers\n"); + if (orig_a0 != A0_OLD) + perr_and_exit("unexpected orig_a0: 0x%lx\n", orig_a0); + + /* Modify a0/orig_a0 for the syscall */ + switch (opt) { + case A0_MODIFY: + regs.a0 = A0_NEW; + break; + case ORIG_A0_MODIFY: + orig_a0 = A0_NEW; + break; + } + + if (ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &iov)) + perr_and_exit("failed to set tracee registers\n"); + if (ptrace(PTRACE_SETREGSET, pid, NT_RISCV_ORIG_A0, &a0_iov)) + perr_and_exit("failed to set tracee registers\n"); + + if (ptrace(PTRACE_GET_SYSCALL_INFO, pid, PTRACE_SYSCALL_INFO_ENTRY, &syscall_info_entry)) + perr_and_exit("failed to get syscall info of entry\n"); + result->orig_a0 = syscall_info_entry->entry.args[0]; + if (ptrace(PTRACE_GET_SYSCALL_INFO, pid, PTRACE_SYSCALL_INFO_EXIT, &syscall_info_exit)) + perr_and_exit("failed to get syscall info of exit\n"); + result->a0 = syscall_info_exit->exit.rval; + + /* Resume the tracee */ + ptrace(PTRACE_CONT, pid, 0, 0); + if (waitpid(pid, &status, 0) != pid) + perr_and_exit("failed to wait for the tracee\n"); + +} + +TEST(ptrace_modify_a0) +{ + struct a0_regs result; + + ptrace_test(A0_MODIFY, &result); + + /* The modification of a0 cannot affect the first argument of the syscall */ + EXPECT_EQ(A0_OLD, result.orig_a0); + EXPECT_EQ(A0_NEW, result.a0); +} + +TEST(ptrace_modify_orig_a0) +{ + struct a0_regs result; + + ptrace_test(ORIG_A0_MODIFY, &result); + + /* Only modify orig_a0 to change the first argument of the syscall */ + EXPECT_EQ(A0_NEW, result.orig_a0); + /* a0 will keep default value, orig_a0 or -ENOSYS, depends on internal. */ + EXPECT_NE(A0_NEW, result.a0); +} + +TEST_HARNESS_MAIN
On Thu, Dec 26, 2024 at 06:52:52PM +0800, Celeste Liu wrote:
This test checks that orig_a0 allows a syscall argument to be modified, and that changing a0 does not change the syscall argument.
Co-developed-by: Quan Zhou zhouquan@iscas.ac.cn Signed-off-by: Quan Zhou zhouquan@iscas.ac.cn Co-developed-by: Charlie Jenkins charlie@rivosinc.com Signed-off-by: Charlie Jenkins charlie@rivosinc.com Reviewed-by: Björn Töpel bjorn@rivosinc.com Signed-off-by: Celeste Liu uwu@coelacanthus.name
[...]
diff --git a/tools/testing/selftests/riscv/abi/ptrace.c b/tools/testing/selftests/riscv/abi/ptrace.c new file mode 100644 index 0000000000000000000000000000000000000000..023695352215bb5de3f91c1a6f5ea3b4f9373ff9 --- /dev/null +++ b/tools/testing/selftests/riscv/abi/ptrace.c
[...]
- if (ptrace(PTRACE_GET_SYSCALL_INFO, pid, PTRACE_SYSCALL_INFO_ENTRY, &syscall_info_entry))
perr_and_exit("failed to get syscall info of entry\n");
- result->orig_a0 = syscall_info_entry->entry.args[0];
- if (ptrace(PTRACE_GET_SYSCALL_INFO, pid, PTRACE_SYSCALL_INFO_EXIT, &syscall_info_exit))
perr_and_exit("failed to get syscall info of exit\n");
- result->a0 = syscall_info_exit->exit.rval;
I'm sorry but this is not how PTRACE_GET_SYSCALL_INFO should be used.
PTRACE_GET_SYSCALL_INFO operation takes a pointer and a size, and in this example instead of size you pass constants 1 and 2, which essentially means that both syscall_info_entry->entry.args[0] and syscall_info_exit->exit.rval are not going to be assigned and would just contain some garbage from the stack.
Also, PTRACE_GET_SYSCALL_INFO operation returns the number of bytes available to be written by the kernel, which is always nonzero on any PTRACE_GET_SYSCALL_INFO-capable kernel. In other words, this example will always end up with perr_and_exit() call.
I wonder how this test was tested before the submission.
On 2024-12-26 21:35, Dmitry V. Levin wrote:
On Thu, Dec 26, 2024 at 06:52:52PM +0800, Celeste Liu wrote:
This test checks that orig_a0 allows a syscall argument to be modified, and that changing a0 does not change the syscall argument.
Co-developed-by: Quan Zhou zhouquan@iscas.ac.cn Signed-off-by: Quan Zhou zhouquan@iscas.ac.cn Co-developed-by: Charlie Jenkins charlie@rivosinc.com Signed-off-by: Charlie Jenkins charlie@rivosinc.com Reviewed-by: Björn Töpel bjorn@rivosinc.com Signed-off-by: Celeste Liu uwu@coelacanthus.name
[...]
diff --git a/tools/testing/selftests/riscv/abi/ptrace.c b/tools/testing/selftests/riscv/abi/ptrace.c new file mode 100644 index 0000000000000000000000000000000000000000..023695352215bb5de3f91c1a6f5ea3b4f9373ff9 --- /dev/null +++ b/tools/testing/selftests/riscv/abi/ptrace.c
[...]
- if (ptrace(PTRACE_GET_SYSCALL_INFO, pid, PTRACE_SYSCALL_INFO_ENTRY, &syscall_info_entry))
perr_and_exit("failed to get syscall info of entry\n");
- result->orig_a0 = syscall_info_entry->entry.args[0];
- if (ptrace(PTRACE_GET_SYSCALL_INFO, pid, PTRACE_SYSCALL_INFO_EXIT, &syscall_info_exit))
perr_and_exit("failed to get syscall info of exit\n");
- result->a0 = syscall_info_exit->exit.rval;
I'm sorry but this is not how PTRACE_GET_SYSCALL_INFO should be used.
PTRACE_GET_SYSCALL_INFO operation takes a pointer and a size, and in this example instead of size you pass constants 1 and 2, which essentially means that both syscall_info_entry->entry.args[0] and syscall_info_exit->exit.rval are not going to be assigned and would just contain some garbage from the stack.
Also, PTRACE_GET_SYSCALL_INFO operation returns the number of bytes available to be written by the kernel, which is always nonzero on any PTRACE_GET_SYSCALL_INFO-capable kernel. In other words, this example will always end up with perr_and_exit() call.
I wonder how this test was tested before the submission.
Oops... It seems I forget sync the code to test board so it runs with the old code... The code is completely not tested... I'm so sorry for my mistake.
I will correct it and test it carefully later...
On Thu, Dec 26, 2024 at 11:21:59PM +0800, Celeste Liu wrote:
On 2024-12-26 21:35, Dmitry V. Levin wrote:
On Thu, Dec 26, 2024 at 06:52:52PM +0800, Celeste Liu wrote:
This test checks that orig_a0 allows a syscall argument to be modified, and that changing a0 does not change the syscall argument.
Co-developed-by: Quan Zhou zhouquan@iscas.ac.cn Signed-off-by: Quan Zhou zhouquan@iscas.ac.cn Co-developed-by: Charlie Jenkins charlie@rivosinc.com Signed-off-by: Charlie Jenkins charlie@rivosinc.com Reviewed-by: Björn Töpel bjorn@rivosinc.com Signed-off-by: Celeste Liu uwu@coelacanthus.name
[...]
diff --git a/tools/testing/selftests/riscv/abi/ptrace.c b/tools/testing/selftests/riscv/abi/ptrace.c new file mode 100644 index 0000000000000000000000000000000000000000..023695352215bb5de3f91c1a6f5ea3b4f9373ff9 --- /dev/null +++ b/tools/testing/selftests/riscv/abi/ptrace.c
[...]
- if (ptrace(PTRACE_GET_SYSCALL_INFO, pid, PTRACE_SYSCALL_INFO_ENTRY, &syscall_info_entry))
perr_and_exit("failed to get syscall info of entry\n");
- result->orig_a0 = syscall_info_entry->entry.args[0];
- if (ptrace(PTRACE_GET_SYSCALL_INFO, pid, PTRACE_SYSCALL_INFO_EXIT, &syscall_info_exit))
perr_and_exit("failed to get syscall info of exit\n");
- result->a0 = syscall_info_exit->exit.rval;
I'm sorry but this is not how PTRACE_GET_SYSCALL_INFO should be used.
PTRACE_GET_SYSCALL_INFO operation takes a pointer and a size, and in this example instead of size you pass constants 1 and 2, which essentially means that both syscall_info_entry->entry.args[0] and syscall_info_exit->exit.rval are not going to be assigned and would just contain some garbage from the stack.
Also, PTRACE_GET_SYSCALL_INFO operation returns the number of bytes available to be written by the kernel, which is always nonzero on any PTRACE_GET_SYSCALL_INFO-capable kernel. In other words, this example will always end up with perr_and_exit() call.
I wonder how this test was tested before the submission.
Oops... It seems I forget sync the code to test board so it runs with the old code... The code is completely not tested... I'm so sorry for my mistake.
I will correct it and test it carefully later...
It would be great to get this into 6.14. Let me know if you would like any help!
- Charlie
On 2025-01-10 11:34, Charlie Jenkins wrote:
On Thu, Dec 26, 2024 at 11:21:59PM +0800, Celeste Liu wrote:
On 2024-12-26 21:35, Dmitry V. Levin wrote:
On Thu, Dec 26, 2024 at 06:52:52PM +0800, Celeste Liu wrote:
This test checks that orig_a0 allows a syscall argument to be modified, and that changing a0 does not change the syscall argument.
Co-developed-by: Quan Zhou zhouquan@iscas.ac.cn Signed-off-by: Quan Zhou zhouquan@iscas.ac.cn Co-developed-by: Charlie Jenkins charlie@rivosinc.com Signed-off-by: Charlie Jenkins charlie@rivosinc.com Reviewed-by: Björn Töpel bjorn@rivosinc.com Signed-off-by: Celeste Liu uwu@coelacanthus.name
[...]
diff --git a/tools/testing/selftests/riscv/abi/ptrace.c b/tools/testing/selftests/riscv/abi/ptrace.c new file mode 100644 index 0000000000000000000000000000000000000000..023695352215bb5de3f91c1a6f5ea3b4f9373ff9 --- /dev/null +++ b/tools/testing/selftests/riscv/abi/ptrace.c
[...]
- if (ptrace(PTRACE_GET_SYSCALL_INFO, pid, PTRACE_SYSCALL_INFO_ENTRY, &syscall_info_entry))
perr_and_exit("failed to get syscall info of entry\n");
- result->orig_a0 = syscall_info_entry->entry.args[0];
- if (ptrace(PTRACE_GET_SYSCALL_INFO, pid, PTRACE_SYSCALL_INFO_EXIT, &syscall_info_exit))
perr_and_exit("failed to get syscall info of exit\n");
- result->a0 = syscall_info_exit->exit.rval;
I'm sorry but this is not how PTRACE_GET_SYSCALL_INFO should be used.
PTRACE_GET_SYSCALL_INFO operation takes a pointer and a size, and in this example instead of size you pass constants 1 and 2, which essentially means that both syscall_info_entry->entry.args[0] and syscall_info_exit->exit.rval are not going to be assigned and would just contain some garbage from the stack.
Also, PTRACE_GET_SYSCALL_INFO operation returns the number of bytes available to be written by the kernel, which is always nonzero on any PTRACE_GET_SYSCALL_INFO-capable kernel. In other words, this example will always end up with perr_and_exit() call.
I wonder how this test was tested before the submission.
Oops... It seems I forget sync the code to test board so it runs with the old code... The code is completely not tested... I'm so sorry for my mistake.
I will correct it and test it carefully later...
It would be great to get this into 6.14. Let me know if you would like any help!
Sorry, delayed due to personal reasons. I have returned to this job recently. The update patchset will be sent tomorrow.
- Charlie
On 2025-01-10 11:34, Charlie Jenkins wrote:
On Thu, Dec 26, 2024 at 11:21:59PM +0800, Celeste Liu wrote:
On 2024-12-26 21:35, Dmitry V. Levin wrote:
On Thu, Dec 26, 2024 at 06:52:52PM +0800, Celeste Liu wrote:
This test checks that orig_a0 allows a syscall argument to be modified, and that changing a0 does not change the syscall argument.
Co-developed-by: Quan Zhou zhouquan@iscas.ac.cn Signed-off-by: Quan Zhou zhouquan@iscas.ac.cn Co-developed-by: Charlie Jenkins charlie@rivosinc.com Signed-off-by: Charlie Jenkins charlie@rivosinc.com Reviewed-by: Björn Töpel bjorn@rivosinc.com Signed-off-by: Celeste Liu uwu@coelacanthus.name
[...]
diff --git a/tools/testing/selftests/riscv/abi/ptrace.c b/tools/testing/selftests/riscv/abi/ptrace.c new file mode 100644 index 0000000000000000000000000000000000000000..023695352215bb5de3f91c1a6f5ea3b4f9373ff9 --- /dev/null +++ b/tools/testing/selftests/riscv/abi/ptrace.c
[...]
- if (ptrace(PTRACE_GET_SYSCALL_INFO, pid, PTRACE_SYSCALL_INFO_ENTRY, &syscall_info_entry))
perr_and_exit("failed to get syscall info of entry\n");
- result->orig_a0 = syscall_info_entry->entry.args[0];
- if (ptrace(PTRACE_GET_SYSCALL_INFO, pid, PTRACE_SYSCALL_INFO_EXIT, &syscall_info_exit))
perr_and_exit("failed to get syscall info of exit\n");
- result->a0 = syscall_info_exit->exit.rval;
I'm sorry but this is not how PTRACE_GET_SYSCALL_INFO should be used.
PTRACE_GET_SYSCALL_INFO operation takes a pointer and a size, and in this example instead of size you pass constants 1 and 2, which essentially means that both syscall_info_entry->entry.args[0] and syscall_info_exit->exit.rval are not going to be assigned and would just contain some garbage from the stack.
Also, PTRACE_GET_SYSCALL_INFO operation returns the number of bytes available to be written by the kernel, which is always nonzero on any PTRACE_GET_SYSCALL_INFO-capable kernel. In other words, this example will always end up with perr_and_exit() call.
I wonder how this test was tested before the submission.
Oops... It seems I forget sync the code to test board so it runs with the old code... The code is completely not tested... I'm so sorry for my mistake.
I will correct it and test it carefully later...
It would be great to get this into 6.14. Let me know if you would like any help!
v5 has been sent.
Sorry for delay. My test environment was broken yesterday so I have to spend time to repair it first...
https://lore.kernel.org/lkml/20250115-riscv-new-regset-v5-0-d0e6ec031a23@coe...
- Charlie
linux-kselftest-mirror@lists.linaro.org