forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/arch/xtensa/kernel/ptrace.c
....@@ -12,35 +12,226 @@
1212 * Marc Gauthier<marc@tensilica.com> <marc@alumni.uwaterloo.ca>
1313 */
1414
15
+#include <linux/audit.h>
1516 #include <linux/errno.h>
1617 #include <linux/hw_breakpoint.h>
1718 #include <linux/kernel.h>
1819 #include <linux/mm.h>
1920 #include <linux/perf_event.h>
2021 #include <linux/ptrace.h>
22
+#include <linux/regset.h>
2123 #include <linux/sched.h>
2224 #include <linux/sched/task_stack.h>
25
+#include <linux/seccomp.h>
2326 #include <linux/security.h>
2427 #include <linux/signal.h>
2528 #include <linux/smp.h>
2629 #include <linux/tracehook.h>
2730 #include <linux/uaccess.h>
2831
32
+#define CREATE_TRACE_POINTS
33
+#include <trace/events/syscalls.h>
34
+
2935 #include <asm/coprocessor.h>
3036 #include <asm/elf.h>
3137 #include <asm/page.h>
32
-#include <asm/pgtable.h>
3338 #include <asm/ptrace.h>
3439
40
+static int gpr_get(struct task_struct *target,
41
+ const struct user_regset *regset,
42
+ struct membuf to)
43
+{
44
+ struct pt_regs *regs = task_pt_regs(target);
45
+ struct user_pt_regs newregs = {
46
+ .pc = regs->pc,
47
+ .ps = regs->ps & ~(1 << PS_EXCM_BIT),
48
+ .lbeg = regs->lbeg,
49
+ .lend = regs->lend,
50
+ .lcount = regs->lcount,
51
+ .sar = regs->sar,
52
+ .threadptr = regs->threadptr,
53
+ .windowbase = regs->windowbase,
54
+ .windowstart = regs->windowstart,
55
+ .syscall = regs->syscall,
56
+ };
57
+
58
+ memcpy(newregs.a,
59
+ regs->areg + XCHAL_NUM_AREGS - regs->windowbase * 4,
60
+ regs->windowbase * 16);
61
+ memcpy(newregs.a + regs->windowbase * 4,
62
+ regs->areg,
63
+ (WSBITS - regs->windowbase) * 16);
64
+
65
+ return membuf_write(&to, &newregs, sizeof(newregs));
66
+}
67
+
68
+static int gpr_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 user_pt_regs newregs = {0};
75
+ struct pt_regs *regs;
76
+ const u32 ps_mask = PS_CALLINC_MASK | PS_OWB_MASK;
77
+
78
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1);
79
+ if (ret)
80
+ return ret;
81
+
82
+ if (newregs.windowbase >= XCHAL_NUM_AREGS / 4)
83
+ return -EINVAL;
84
+
85
+ regs = task_pt_regs(target);
86
+ regs->pc = newregs.pc;
87
+ regs->ps = (regs->ps & ~ps_mask) | (newregs.ps & ps_mask);
88
+ regs->lbeg = newregs.lbeg;
89
+ regs->lend = newregs.lend;
90
+ regs->lcount = newregs.lcount;
91
+ regs->sar = newregs.sar;
92
+ regs->threadptr = newregs.threadptr;
93
+
94
+ if (newregs.syscall)
95
+ regs->syscall = newregs.syscall;
96
+
97
+ if (newregs.windowbase != regs->windowbase ||
98
+ newregs.windowstart != regs->windowstart) {
99
+ u32 rotws, wmask;
100
+
101
+ rotws = (((newregs.windowstart |
102
+ (newregs.windowstart << WSBITS)) >>
103
+ newregs.windowbase) &
104
+ ((1 << WSBITS) - 1)) & ~1;
105
+ wmask = ((rotws ? WSBITS + 1 - ffs(rotws) : 0) << 4) |
106
+ (rotws & 0xF) | 1;
107
+ regs->windowbase = newregs.windowbase;
108
+ regs->windowstart = newregs.windowstart;
109
+ regs->wmask = wmask;
110
+ }
111
+
112
+ memcpy(regs->areg + XCHAL_NUM_AREGS - newregs.windowbase * 4,
113
+ newregs.a, newregs.windowbase * 16);
114
+ memcpy(regs->areg, newregs.a + newregs.windowbase * 4,
115
+ (WSBITS - newregs.windowbase) * 16);
116
+
117
+ return 0;
118
+}
119
+
120
+static int tie_get(struct task_struct *target,
121
+ const struct user_regset *regset,
122
+ struct membuf to)
123
+{
124
+ int ret;
125
+ struct pt_regs *regs = task_pt_regs(target);
126
+ struct thread_info *ti = task_thread_info(target);
127
+ elf_xtregs_t *newregs = kzalloc(sizeof(elf_xtregs_t), GFP_KERNEL);
128
+
129
+ if (!newregs)
130
+ return -ENOMEM;
131
+
132
+ newregs->opt = regs->xtregs_opt;
133
+ newregs->user = ti->xtregs_user;
134
+
135
+#if XTENSA_HAVE_COPROCESSORS
136
+ /* Flush all coprocessor registers to memory. */
137
+ coprocessor_flush_all(ti);
138
+ newregs->cp0 = ti->xtregs_cp.cp0;
139
+ newregs->cp1 = ti->xtregs_cp.cp1;
140
+ newregs->cp2 = ti->xtregs_cp.cp2;
141
+ newregs->cp3 = ti->xtregs_cp.cp3;
142
+ newregs->cp4 = ti->xtregs_cp.cp4;
143
+ newregs->cp5 = ti->xtregs_cp.cp5;
144
+ newregs->cp6 = ti->xtregs_cp.cp6;
145
+ newregs->cp7 = ti->xtregs_cp.cp7;
146
+#endif
147
+ ret = membuf_write(&to, newregs, sizeof(*newregs));
148
+ kfree(newregs);
149
+ return ret;
150
+}
151
+
152
+static int tie_set(struct task_struct *target,
153
+ const struct user_regset *regset,
154
+ unsigned int pos, unsigned int count,
155
+ const void *kbuf, const void __user *ubuf)
156
+{
157
+ int ret;
158
+ struct pt_regs *regs = task_pt_regs(target);
159
+ struct thread_info *ti = task_thread_info(target);
160
+ elf_xtregs_t *newregs = kzalloc(sizeof(elf_xtregs_t), GFP_KERNEL);
161
+
162
+ if (!newregs)
163
+ return -ENOMEM;
164
+
165
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
166
+ newregs, 0, -1);
167
+
168
+ if (ret)
169
+ goto exit;
170
+ regs->xtregs_opt = newregs->opt;
171
+ ti->xtregs_user = newregs->user;
172
+
173
+#if XTENSA_HAVE_COPROCESSORS
174
+ /* Flush all coprocessors before we overwrite them. */
175
+ coprocessor_flush_all(ti);
176
+ coprocessor_release_all(ti);
177
+ ti->xtregs_cp.cp0 = newregs->cp0;
178
+ ti->xtregs_cp.cp1 = newregs->cp1;
179
+ ti->xtregs_cp.cp2 = newregs->cp2;
180
+ ti->xtregs_cp.cp3 = newregs->cp3;
181
+ ti->xtregs_cp.cp4 = newregs->cp4;
182
+ ti->xtregs_cp.cp5 = newregs->cp5;
183
+ ti->xtregs_cp.cp6 = newregs->cp6;
184
+ ti->xtregs_cp.cp7 = newregs->cp7;
185
+#endif
186
+exit:
187
+ kfree(newregs);
188
+ return ret;
189
+}
190
+
191
+enum xtensa_regset {
192
+ REGSET_GPR,
193
+ REGSET_TIE,
194
+};
195
+
196
+static const struct user_regset xtensa_regsets[] = {
197
+ [REGSET_GPR] = {
198
+ .core_note_type = NT_PRSTATUS,
199
+ .n = sizeof(struct user_pt_regs) / sizeof(u32),
200
+ .size = sizeof(u32),
201
+ .align = sizeof(u32),
202
+ .regset_get = gpr_get,
203
+ .set = gpr_set,
204
+ },
205
+ [REGSET_TIE] = {
206
+ .core_note_type = NT_PRFPREG,
207
+ .n = sizeof(elf_xtregs_t) / sizeof(u32),
208
+ .size = sizeof(u32),
209
+ .align = sizeof(u32),
210
+ .regset_get = tie_get,
211
+ .set = tie_set,
212
+ },
213
+};
214
+
215
+static const struct user_regset_view user_xtensa_view = {
216
+ .name = "xtensa",
217
+ .e_machine = EM_XTENSA,
218
+ .regsets = xtensa_regsets,
219
+ .n = ARRAY_SIZE(xtensa_regsets)
220
+};
221
+
222
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
223
+{
224
+ return &user_xtensa_view;
225
+}
35226
36227 void user_enable_single_step(struct task_struct *child)
37228 {
38
- child->ptrace |= PT_SINGLESTEP;
229
+ set_tsk_thread_flag(child, TIF_SINGLESTEP);
39230 }
40231
41232 void user_disable_single_step(struct task_struct *child)
42233 {
43
- child->ptrace &= ~PT_SINGLESTEP;
234
+ clear_tsk_thread_flag(child, TIF_SINGLESTEP);
44235 }
45236
46237 /*
....@@ -54,161 +245,26 @@
54245
55246 static int ptrace_getregs(struct task_struct *child, void __user *uregs)
56247 {
57
- struct pt_regs *regs = task_pt_regs(child);
58
- xtensa_gregset_t __user *gregset = uregs;
59
- unsigned long wb = regs->windowbase;
60
- int i;
61
-
62
- if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t)))
63
- return -EIO;
64
-
65
- __put_user(regs->pc, &gregset->pc);
66
- __put_user(regs->ps & ~(1 << PS_EXCM_BIT), &gregset->ps);
67
- __put_user(regs->lbeg, &gregset->lbeg);
68
- __put_user(regs->lend, &gregset->lend);
69
- __put_user(regs->lcount, &gregset->lcount);
70
- __put_user(regs->windowstart, &gregset->windowstart);
71
- __put_user(regs->windowbase, &gregset->windowbase);
72
- __put_user(regs->threadptr, &gregset->threadptr);
73
-
74
- for (i = 0; i < XCHAL_NUM_AREGS; i++)
75
- __put_user(regs->areg[i],
76
- gregset->a + ((wb * 4 + i) % XCHAL_NUM_AREGS));
77
-
78
- return 0;
248
+ return copy_regset_to_user(child, &user_xtensa_view, REGSET_GPR,
249
+ 0, sizeof(xtensa_gregset_t), uregs);
79250 }
80251
81252 static int ptrace_setregs(struct task_struct *child, void __user *uregs)
82253 {
83
- struct pt_regs *regs = task_pt_regs(child);
84
- xtensa_gregset_t *gregset = uregs;
85
- const unsigned long ps_mask = PS_CALLINC_MASK | PS_OWB_MASK;
86
- unsigned long ps;
87
- unsigned long wb, ws;
88
-
89
- if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t)))
90
- return -EIO;
91
-
92
- __get_user(regs->pc, &gregset->pc);
93
- __get_user(ps, &gregset->ps);
94
- __get_user(regs->lbeg, &gregset->lbeg);
95
- __get_user(regs->lend, &gregset->lend);
96
- __get_user(regs->lcount, &gregset->lcount);
97
- __get_user(ws, &gregset->windowstart);
98
- __get_user(wb, &gregset->windowbase);
99
- __get_user(regs->threadptr, &gregset->threadptr);
100
-
101
- regs->ps = (regs->ps & ~ps_mask) | (ps & ps_mask) | (1 << PS_EXCM_BIT);
102
-
103
- if (wb >= XCHAL_NUM_AREGS / 4)
104
- return -EFAULT;
105
-
106
- if (wb != regs->windowbase || ws != regs->windowstart) {
107
- unsigned long rotws, wmask;
108
-
109
- rotws = (((ws | (ws << WSBITS)) >> wb) &
110
- ((1 << WSBITS) - 1)) & ~1;
111
- wmask = ((rotws ? WSBITS + 1 - ffs(rotws) : 0) << 4) |
112
- (rotws & 0xF) | 1;
113
- regs->windowbase = wb;
114
- regs->windowstart = ws;
115
- regs->wmask = wmask;
116
- }
117
-
118
- if (wb != 0 && __copy_from_user(regs->areg + XCHAL_NUM_AREGS - wb * 4,
119
- gregset->a, wb * 16))
120
- return -EFAULT;
121
-
122
- if (__copy_from_user(regs->areg, gregset->a + wb * 4,
123
- (WSBITS - wb) * 16))
124
- return -EFAULT;
125
-
126
- return 0;
254
+ return copy_regset_from_user(child, &user_xtensa_view, REGSET_GPR,
255
+ 0, sizeof(xtensa_gregset_t), uregs);
127256 }
128
-
129
-
130
-#if XTENSA_HAVE_COPROCESSORS
131
-#define CP_OFFSETS(cp) \
132
- { \
133
- .elf_xtregs_offset = offsetof(elf_xtregs_t, cp), \
134
- .ti_offset = offsetof(struct thread_info, xtregs_cp.cp), \
135
- .sz = sizeof(xtregs_ ## cp ## _t), \
136
- }
137
-
138
-static const struct {
139
- size_t elf_xtregs_offset;
140
- size_t ti_offset;
141
- size_t sz;
142
-} cp_offsets[] = {
143
- CP_OFFSETS(cp0),
144
- CP_OFFSETS(cp1),
145
- CP_OFFSETS(cp2),
146
- CP_OFFSETS(cp3),
147
- CP_OFFSETS(cp4),
148
- CP_OFFSETS(cp5),
149
- CP_OFFSETS(cp6),
150
- CP_OFFSETS(cp7),
151
-};
152
-#endif
153257
154258 static int ptrace_getxregs(struct task_struct *child, void __user *uregs)
155259 {
156
- struct pt_regs *regs = task_pt_regs(child);
157
- struct thread_info *ti = task_thread_info(child);
158
- elf_xtregs_t __user *xtregs = uregs;
159
- int ret = 0;
160
- int i __maybe_unused;
161
-
162
- if (!access_ok(VERIFY_WRITE, uregs, sizeof(elf_xtregs_t)))
163
- return -EIO;
164
-
165
-#if XTENSA_HAVE_COPROCESSORS
166
- /* Flush all coprocessor registers to memory. */
167
- coprocessor_flush_all(ti);
168
-
169
- for (i = 0; i < ARRAY_SIZE(cp_offsets); ++i)
170
- ret |= __copy_to_user((char __user *)xtregs +
171
- cp_offsets[i].elf_xtregs_offset,
172
- (const char *)ti +
173
- cp_offsets[i].ti_offset,
174
- cp_offsets[i].sz);
175
-#endif
176
- ret |= __copy_to_user(&xtregs->opt, &regs->xtregs_opt,
177
- sizeof(xtregs->opt));
178
- ret |= __copy_to_user(&xtregs->user,&ti->xtregs_user,
179
- sizeof(xtregs->user));
180
-
181
- return ret ? -EFAULT : 0;
260
+ return copy_regset_to_user(child, &user_xtensa_view, REGSET_TIE,
261
+ 0, sizeof(elf_xtregs_t), uregs);
182262 }
183263
184264 static int ptrace_setxregs(struct task_struct *child, void __user *uregs)
185265 {
186
- struct thread_info *ti = task_thread_info(child);
187
- struct pt_regs *regs = task_pt_regs(child);
188
- elf_xtregs_t *xtregs = uregs;
189
- int ret = 0;
190
- int i __maybe_unused;
191
-
192
- if (!access_ok(VERIFY_READ, uregs, sizeof(elf_xtregs_t)))
193
- return -EFAULT;
194
-
195
-#if XTENSA_HAVE_COPROCESSORS
196
- /* Flush all coprocessors before we overwrite them. */
197
- coprocessor_flush_all(ti);
198
- coprocessor_release_all(ti);
199
-
200
- for (i = 0; i < ARRAY_SIZE(cp_offsets); ++i)
201
- ret |= __copy_from_user((char *)ti + cp_offsets[i].ti_offset,
202
- (const char __user *)xtregs +
203
- cp_offsets[i].elf_xtregs_offset,
204
- cp_offsets[i].sz);
205
-#endif
206
- ret |= __copy_from_user(&regs->xtregs_opt, &xtregs->opt,
207
- sizeof(xtregs->opt));
208
- ret |= __copy_from_user(&ti->xtregs_user, &xtregs->user,
209
- sizeof(xtregs->user));
210
-
211
- return ret ? -EFAULT : 0;
266
+ return copy_regset_from_user(child, &user_xtensa_view, REGSET_TIE,
267
+ 0, sizeof(elf_xtregs_t), uregs);
212268 }
213269
214270 static int ptrace_peekusr(struct task_struct *child, long regno,
....@@ -447,18 +503,8 @@
447503 void __user *datap = (void __user *) data;
448504
449505 switch (request) {
450
- case PTRACE_PEEKTEXT: /* read word at location addr. */
451
- case PTRACE_PEEKDATA:
452
- ret = generic_ptrace_peekdata(child, addr, data);
453
- break;
454
-
455506 case PTRACE_PEEKUSR: /* read register specified by addr. */
456507 ret = ptrace_peekusr(child, addr, datap);
457
- break;
458
-
459
- case PTRACE_POKETEXT: /* write the word at location addr. */
460
- case PTRACE_POKEDATA:
461
- ret = generic_ptrace_pokedata(child, addr, data);
462508 break;
463509
464510 case PTRACE_POKEUSR: /* write register specified by addr. */
....@@ -497,19 +543,43 @@
497543 return ret;
498544 }
499545
500
-unsigned long do_syscall_trace_enter(struct pt_regs *regs)
546
+void do_syscall_trace_leave(struct pt_regs *regs);
547
+int do_syscall_trace_enter(struct pt_regs *regs)
501548 {
502
- if (test_thread_flag(TIF_SYSCALL_TRACE) &&
503
- tracehook_report_syscall_entry(regs))
504
- return -1;
549
+ if (regs->syscall == NO_SYSCALL)
550
+ regs->areg[2] = -ENOSYS;
505551
506
- return regs->areg[2];
552
+ if (test_thread_flag(TIF_SYSCALL_TRACE) &&
553
+ tracehook_report_syscall_entry(regs)) {
554
+ regs->areg[2] = -ENOSYS;
555
+ regs->syscall = NO_SYSCALL;
556
+ return 0;
557
+ }
558
+
559
+ if (regs->syscall == NO_SYSCALL ||
560
+ secure_computing() == -1) {
561
+ do_syscall_trace_leave(regs);
562
+ return 0;
563
+ }
564
+
565
+ if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
566
+ trace_sys_enter(regs, syscall_get_nr(current, regs));
567
+
568
+ audit_syscall_entry(regs->syscall, regs->areg[6],
569
+ regs->areg[3], regs->areg[4],
570
+ regs->areg[5]);
571
+ return 1;
507572 }
508573
509574 void do_syscall_trace_leave(struct pt_regs *regs)
510575 {
511576 int step;
512577
578
+ audit_syscall_exit(regs);
579
+
580
+ if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
581
+ trace_sys_exit(regs, regs_return_value(regs));
582
+
513583 step = test_thread_flag(TIF_SINGLESTEP);
514584
515585 if (step || test_thread_flag(TIF_SYSCALL_TRACE))