hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/arch/riscv/kernel/ptrace.c
....@@ -1,16 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright 2010 Tilera Corporation. All Rights Reserved.
34 * Copyright 2015 Regents of the University of California
45 * Copyright 2017 SiFive
5
- *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of the GNU General Public License
8
- * as published by the Free Software Foundation, version 2.
9
- *
10
- * This program is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- * GNU General Public License for more details.
146 *
157 * Copied from arch/tile/kernel/ptrace.c
168 */
....@@ -18,27 +10,31 @@
1810 #include <asm/ptrace.h>
1911 #include <asm/syscall.h>
2012 #include <asm/thread_info.h>
13
+#include <asm/switch_to.h>
14
+#include <linux/audit.h>
2115 #include <linux/ptrace.h>
2216 #include <linux/elf.h>
2317 #include <linux/regset.h>
2418 #include <linux/sched.h>
2519 #include <linux/sched/task_stack.h>
2620 #include <linux/tracehook.h>
21
+
22
+#define CREATE_TRACE_POINTS
2723 #include <trace/events/syscalls.h>
2824
2925 enum riscv_regset {
3026 REGSET_X,
27
+#ifdef CONFIG_FPU
28
+ REGSET_F,
29
+#endif
3130 };
3231
3332 static int riscv_gpr_get(struct task_struct *target,
3433 const struct user_regset *regset,
35
- unsigned int pos, unsigned int count,
36
- void *kbuf, void __user *ubuf)
34
+ struct membuf to)
3735 {
38
- struct pt_regs *regs;
39
-
40
- regs = task_pt_regs(target);
41
- return user_regset_copyout(&pos, &count, &kbuf, &ubuf, regs, 0, -1);
36
+ return membuf_write(&to, task_pt_regs(target),
37
+ sizeof(struct user_regs_struct));
4238 }
4339
4440 static int riscv_gpr_set(struct task_struct *target,
....@@ -54,6 +50,40 @@
5450 return ret;
5551 }
5652
53
+#ifdef CONFIG_FPU
54
+static int riscv_fpr_get(struct task_struct *target,
55
+ const struct user_regset *regset,
56
+ struct membuf to)
57
+{
58
+ struct __riscv_d_ext_state *fstate = &target->thread.fstate;
59
+
60
+ if (target == current)
61
+ fstate_save(current, task_pt_regs(current));
62
+
63
+ membuf_write(&to, fstate, offsetof(struct __riscv_d_ext_state, fcsr));
64
+ membuf_store(&to, fstate->fcsr);
65
+ return membuf_zero(&to, 4); // explicitly pad
66
+}
67
+
68
+static int riscv_fpr_set(struct task_struct *target,
69
+ const struct user_regset *regset,
70
+ unsigned int pos, unsigned int count,
71
+ const void *kbuf, const void __user *ubuf)
72
+{
73
+ int ret;
74
+ struct __riscv_d_ext_state *fstate = &target->thread.fstate;
75
+
76
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, fstate, 0,
77
+ offsetof(struct __riscv_d_ext_state, fcsr));
78
+ if (!ret) {
79
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, fstate, 0,
80
+ offsetof(struct __riscv_d_ext_state, fcsr) +
81
+ sizeof(fstate->fcsr));
82
+ }
83
+
84
+ return ret;
85
+}
86
+#endif
5787
5888 static const struct user_regset riscv_user_regset[] = {
5989 [REGSET_X] = {
....@@ -61,9 +91,19 @@
6191 .n = ELF_NGREG,
6292 .size = sizeof(elf_greg_t),
6393 .align = sizeof(elf_greg_t),
64
- .get = &riscv_gpr_get,
65
- .set = &riscv_gpr_set,
94
+ .regset_get = riscv_gpr_get,
95
+ .set = riscv_gpr_set,
6696 },
97
+#ifdef CONFIG_FPU
98
+ [REGSET_F] = {
99
+ .core_note_type = NT_PRFPREG,
100
+ .n = ELF_NFPREG,
101
+ .size = sizeof(elf_fpreg_t),
102
+ .align = sizeof(elf_fpreg_t),
103
+ .regset_get = riscv_fpr_get,
104
+ .set = riscv_fpr_set,
105
+ },
106
+#endif
67107 };
68108
69109 static const struct user_regset_view riscv_user_native_view = {
....@@ -101,20 +141,33 @@
101141 * Allows PTRACE_SYSCALL to work. These are called from entry.S in
102142 * {handle,ret_from}_syscall.
103143 */
104
-void do_syscall_trace_enter(struct pt_regs *regs)
144
+__visible int do_syscall_trace_enter(struct pt_regs *regs)
105145 {
106146 if (test_thread_flag(TIF_SYSCALL_TRACE))
107147 if (tracehook_report_syscall_entry(regs))
108
- syscall_set_nr(current, regs, -1);
148
+ return -1;
149
+
150
+ /*
151
+ * Do the secure computing after ptrace; failures should be fast.
152
+ * If this fails we might have return value in a0 from seccomp
153
+ * (via SECCOMP_RET_ERRNO/TRACE).
154
+ */
155
+ if (secure_computing() == -1)
156
+ return -1;
109157
110158 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
111159 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
112160 trace_sys_enter(regs, syscall_get_nr(current, regs));
113161 #endif
162
+
163
+ audit_syscall_entry(regs->a7, regs->a0, regs->a1, regs->a2, regs->a3);
164
+ return 0;
114165 }
115166
116
-void do_syscall_trace_exit(struct pt_regs *regs)
167
+__visible void do_syscall_trace_exit(struct pt_regs *regs)
117168 {
169
+ audit_syscall_exit(regs);
170
+
118171 if (test_thread_flag(TIF_SYSCALL_TRACE))
119172 tracehook_report_syscall_exit(regs, 0);
120173