^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * OpenRISC ptrace.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Linux architectural port borrowing liberally from similar works of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * others. All original copyrights apply as per the original source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * declaration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Modifications for the OpenRISC architecture:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright (C) 2005 Gyorgy Jeney <nog@bsemi.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/sched/task_stack.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/audit.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/regset.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/tracehook.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/elf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <asm/thread_info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <asm/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * Copy the thread state to a regset that can be interpreted by userspace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * It doesn't matter what our internal pt_regs structure looks like. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * important thing is that we export a consistent view of the thread state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * to userspace. As such, we need to make sure that the regset remains
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * ABI compatible as defined by the struct user_regs_struct:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * (Each item is a 32-bit word)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * r0 = 0 (exported for clarity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * 31 GPRS r1-r31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * PC (Program counter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * SR (Supervision register)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static int genregs_get(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct membuf to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) const struct pt_regs *regs = task_pt_regs(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* r0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) membuf_zero(&to, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) membuf_write(&to, regs->gpr + 1, 31 * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) membuf_store(&to, regs->pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return membuf_store(&to, regs->sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * Set the thread state from a regset passed in via ptrace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static int genregs_set(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned int pos, unsigned int count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) const void *kbuf, const void __user * ubuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct pt_regs *regs = task_pt_regs(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* ignore r0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* r1 - r31 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) regs->gpr+1, 4, 4*32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* PC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) ®s->pc, 4*32, 4*33);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * Skip SR and padding... userspace isn't allowed to changes bits in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * the Supervision register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) 4*33, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * Define the register sets available on OpenRISC under Linux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) enum or1k_regset {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) REGSET_GENERAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static const struct user_regset or1k_regsets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) [REGSET_GENERAL] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .core_note_type = NT_PRSTATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .n = ELF_NGREG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .size = sizeof(long),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .align = sizeof(long),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .regset_get = genregs_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .set = genregs_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static const struct user_regset_view user_or1k_native_view = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .name = "or1k",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .e_machine = EM_OPENRISC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .regsets = or1k_regsets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .n = ARRAY_SIZE(or1k_regsets),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) const struct user_regset_view *task_user_regset_view(struct task_struct *task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return &user_or1k_native_view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * does not yet catch signals sent when the child dies.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * in exit.c or in signal.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * Called by kernel/ptrace.c when detaching..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * Make sure the single step bit is not set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) void ptrace_disable(struct task_struct *child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) pr_debug("ptrace_disable(): TODO\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) user_disable_single_step(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) long arch_ptrace(struct task_struct *child, long request, unsigned long addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) unsigned long data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) switch (request) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) ret = ptrace_request(child, request, addr, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * Notification of system call entry/exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * - triggered by current->work.syscall_trace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) long ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (test_thread_flag(TIF_SYSCALL_TRACE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) tracehook_report_syscall_entry(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * Tracing decided this syscall should not happen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * We'll return a bogus call number to get an ENOSYS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * error, but leave the original number in <something>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ret = -1L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) audit_syscall_entry(regs->gpr[11], regs->gpr[3], regs->gpr[4],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) regs->gpr[5], regs->gpr[6]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return ret ? : regs->gpr[11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) int step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) audit_syscall_exit(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) step = test_thread_flag(TIF_SINGLESTEP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (step || test_thread_flag(TIF_SYSCALL_TRACE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) tracehook_report_syscall_exit(regs, step);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }