| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * SuperH process tracing |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 5 | 6 | * Copyright (C) 2002 - 2009 Paul Mundt |
|---|
| 6 | 7 | * |
|---|
| 7 | 8 | * Audit support by Yuichi Nakamura <ynakam@hitachisoft.jp> |
|---|
| 8 | | - * |
|---|
| 9 | | - * This file is subject to the terms and conditions of the GNU General Public |
|---|
| 10 | | - * License. See the file "COPYING" in the main directory of this archive |
|---|
| 11 | | - * for more details. |
|---|
| 12 | 9 | */ |
|---|
| 13 | 10 | #include <linux/kernel.h> |
|---|
| 14 | 11 | #include <linux/sched.h> |
|---|
| .. | .. |
|---|
| 28 | 25 | #include <linux/regset.h> |
|---|
| 29 | 26 | #include <linux/hw_breakpoint.h> |
|---|
| 30 | 27 | #include <linux/uaccess.h> |
|---|
| 31 | | -#include <asm/pgtable.h> |
|---|
| 32 | 28 | #include <asm/processor.h> |
|---|
| 33 | 29 | #include <asm/mmu_context.h> |
|---|
| 34 | 30 | #include <asm/syscalls.h> |
|---|
| .. | .. |
|---|
| 138 | 134 | |
|---|
| 139 | 135 | static int genregs_get(struct task_struct *target, |
|---|
| 140 | 136 | const struct user_regset *regset, |
|---|
| 141 | | - unsigned int pos, unsigned int count, |
|---|
| 142 | | - void *kbuf, void __user *ubuf) |
|---|
| 137 | + struct membuf to) |
|---|
| 143 | 138 | { |
|---|
| 144 | 139 | const struct pt_regs *regs = task_pt_regs(target); |
|---|
| 145 | | - int ret; |
|---|
| 146 | 140 | |
|---|
| 147 | | - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
|---|
| 148 | | - regs->regs, |
|---|
| 149 | | - 0, 16 * sizeof(unsigned long)); |
|---|
| 150 | | - if (!ret) |
|---|
| 151 | | - /* PC, PR, SR, GBR, MACH, MACL, TRA */ |
|---|
| 152 | | - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
|---|
| 153 | | - ®s->pc, |
|---|
| 154 | | - offsetof(struct pt_regs, pc), |
|---|
| 155 | | - sizeof(struct pt_regs)); |
|---|
| 156 | | - if (!ret) |
|---|
| 157 | | - ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, |
|---|
| 158 | | - sizeof(struct pt_regs), -1); |
|---|
| 159 | | - |
|---|
| 160 | | - return ret; |
|---|
| 141 | + return membuf_write(&to, regs, sizeof(struct pt_regs)); |
|---|
| 161 | 142 | } |
|---|
| 162 | 143 | |
|---|
| 163 | 144 | static int genregs_set(struct task_struct *target, |
|---|
| .. | .. |
|---|
| 184 | 165 | } |
|---|
| 185 | 166 | |
|---|
| 186 | 167 | #ifdef CONFIG_SH_FPU |
|---|
| 187 | | -int fpregs_get(struct task_struct *target, |
|---|
| 168 | +static int fpregs_get(struct task_struct *target, |
|---|
| 188 | 169 | const struct user_regset *regset, |
|---|
| 189 | | - unsigned int pos, unsigned int count, |
|---|
| 190 | | - void *kbuf, void __user *ubuf) |
|---|
| 170 | + struct membuf to) |
|---|
| 191 | 171 | { |
|---|
| 192 | 172 | int ret; |
|---|
| 193 | 173 | |
|---|
| .. | .. |
|---|
| 195 | 175 | if (ret) |
|---|
| 196 | 176 | return ret; |
|---|
| 197 | 177 | |
|---|
| 198 | | - if ((boot_cpu_data.flags & CPU_HAS_FPU)) |
|---|
| 199 | | - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
|---|
| 200 | | - &target->thread.xstate->hardfpu, 0, -1); |
|---|
| 201 | | - |
|---|
| 202 | | - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
|---|
| 203 | | - &target->thread.xstate->softfpu, 0, -1); |
|---|
| 178 | + return membuf_write(&to, target->thread.xstate, |
|---|
| 179 | + sizeof(struct user_fpu_struct)); |
|---|
| 204 | 180 | } |
|---|
| 205 | 181 | |
|---|
| 206 | 182 | static int fpregs_set(struct task_struct *target, |
|---|
| .. | .. |
|---|
| 234 | 210 | #ifdef CONFIG_SH_DSP |
|---|
| 235 | 211 | static int dspregs_get(struct task_struct *target, |
|---|
| 236 | 212 | const struct user_regset *regset, |
|---|
| 237 | | - unsigned int pos, unsigned int count, |
|---|
| 238 | | - void *kbuf, void __user *ubuf) |
|---|
| 213 | + struct membuf to) |
|---|
| 239 | 214 | { |
|---|
| 240 | 215 | const struct pt_dspregs *regs = |
|---|
| 241 | 216 | (struct pt_dspregs *)&target->thread.dsp_status.dsp_regs; |
|---|
| 242 | | - int ret; |
|---|
| 243 | 217 | |
|---|
| 244 | | - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, regs, |
|---|
| 245 | | - 0, sizeof(struct pt_dspregs)); |
|---|
| 246 | | - if (!ret) |
|---|
| 247 | | - ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, |
|---|
| 248 | | - sizeof(struct pt_dspregs), -1); |
|---|
| 249 | | - |
|---|
| 250 | | - return ret; |
|---|
| 218 | + return membuf_write(&to, regs, sizeof(struct pt_dspregs)); |
|---|
| 251 | 219 | } |
|---|
| 252 | 220 | |
|---|
| 253 | 221 | static int dspregs_set(struct task_struct *target, |
|---|
| .. | .. |
|---|
| 328 | 296 | .n = ELF_NGREG, |
|---|
| 329 | 297 | .size = sizeof(long), |
|---|
| 330 | 298 | .align = sizeof(long), |
|---|
| 331 | | - .get = genregs_get, |
|---|
| 299 | + .regset_get = genregs_get, |
|---|
| 332 | 300 | .set = genregs_set, |
|---|
| 333 | 301 | }, |
|---|
| 334 | 302 | |
|---|
| .. | .. |
|---|
| 338 | 306 | .n = sizeof(struct user_fpu_struct) / sizeof(long), |
|---|
| 339 | 307 | .size = sizeof(long), |
|---|
| 340 | 308 | .align = sizeof(long), |
|---|
| 341 | | - .get = fpregs_get, |
|---|
| 309 | + .regset_get = fpregs_get, |
|---|
| 342 | 310 | .set = fpregs_set, |
|---|
| 343 | 311 | .active = fpregs_active, |
|---|
| 344 | 312 | }, |
|---|
| .. | .. |
|---|
| 349 | 317 | .n = sizeof(struct pt_dspregs) / sizeof(long), |
|---|
| 350 | 318 | .size = sizeof(long), |
|---|
| 351 | 319 | .align = sizeof(long), |
|---|
| 352 | | - .get = dspregs_get, |
|---|
| 320 | + .regset_get = dspregs_get, |
|---|
| 353 | 321 | .set = dspregs_set, |
|---|
| 354 | 322 | .active = dspregs_active, |
|---|
| 355 | 323 | }, |
|---|
| .. | .. |
|---|
| 487 | 455 | |
|---|
| 488 | 456 | asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) |
|---|
| 489 | 457 | { |
|---|
| 490 | | - long ret = 0; |
|---|
| 491 | | - |
|---|
| 492 | | - secure_computing_strict(regs->regs[0]); |
|---|
| 493 | | - |
|---|
| 494 | 458 | if (test_thread_flag(TIF_SYSCALL_TRACE) && |
|---|
| 495 | | - tracehook_report_syscall_entry(regs)) |
|---|
| 496 | | - /* |
|---|
| 497 | | - * Tracing decided this syscall should not happen. |
|---|
| 498 | | - * We'll return a bogus call number to get an ENOSYS |
|---|
| 499 | | - * error, but leave the original number in regs->regs[0]. |
|---|
| 500 | | - */ |
|---|
| 501 | | - ret = -1L; |
|---|
| 459 | + tracehook_report_syscall_entry(regs)) { |
|---|
| 460 | + regs->regs[0] = -ENOSYS; |
|---|
| 461 | + return -1; |
|---|
| 462 | + } |
|---|
| 463 | + |
|---|
| 464 | + if (secure_computing() == -1) |
|---|
| 465 | + return -1; |
|---|
| 502 | 466 | |
|---|
| 503 | 467 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) |
|---|
| 504 | 468 | trace_sys_enter(regs, regs->regs[0]); |
|---|
| .. | .. |
|---|
| 506 | 470 | audit_syscall_entry(regs->regs[3], regs->regs[4], regs->regs[5], |
|---|
| 507 | 471 | regs->regs[6], regs->regs[7]); |
|---|
| 508 | 472 | |
|---|
| 509 | | - return ret ?: regs->regs[0]; |
|---|
| 473 | + return 0; |
|---|
| 510 | 474 | } |
|---|
| 511 | 475 | |
|---|
| 512 | 476 | asmlinkage void do_syscall_trace_leave(struct pt_regs *regs) |
|---|