* Martin Schwidefsky (schwidefsky@de.ibm.com)
*/
+#include "asm/ptrace.h"
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/sched/task_stack.h>
#include "compat_ptrace.h"
#endif
-#define CREATE_TRACE_POINTS
-#include <trace/events/syscalls.h>
-
void update_cr_regs(struct task_struct *task)
{
struct pt_regs *regs = task_pt_regs(task);
memset(&task->thread.per_user, 0, sizeof(task->thread.per_user));
memset(&task->thread.per_event, 0, sizeof(task->thread.per_event));
clear_tsk_thread_flag(task, TIF_SINGLE_STEP);
- clear_pt_regs_flag(task_pt_regs(task), PIF_PER_TRAP);
+ clear_tsk_thread_flag(task, TIF_PER_TRAP);
task->thread.per_flags = 0;
}
child->thread.per_user.end = data;
}
-static void fixup_int_code(struct task_struct *child, addr_t data)
-{
- struct pt_regs *regs = task_pt_regs(child);
- int ilc = regs->int_code >> 16;
- u16 insn;
-
- if (ilc > 6)
- return;
-
- if (ptrace_access_vm(child, regs->psw.addr - (regs->int_code >> 16),
- &insn, sizeof(insn), FOLL_FORCE) != sizeof(insn))
- return;
-
- /* double check that tracee stopped on svc instruction */
- if ((insn >> 8) != 0xa)
- return;
-
- regs->int_code = 0x20000 | (data & 0xffff);
-}
/*
* Write a word to the user area of a process at location addr. This
* operation does have an additional problem compared to peek_user.
}
if (test_pt_regs_flag(regs, PIF_SYSCALL) &&
- addr == offsetof(struct user, regs.gprs[2]))
- fixup_int_code(child, data);
- *(addr_t *)((addr_t) ®s->psw + addr) = data;
+ addr == offsetof(struct user, regs.gprs[2])) {
+ struct pt_regs *regs = task_pt_regs(child);
+ regs->int_code = 0x20000 | (data & 0xffff);
+ }
+ *(addr_t *)((addr_t) ®s->psw + addr) = data;
} else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) {
/*
* access registers are stored in the thread structure
regs->psw.mask = (regs->psw.mask & ~PSW_MASK_BA) |
(__u64)(tmp & PSW32_ADDR_AMODE);
} else {
-
if (test_pt_regs_flag(regs, PIF_SYSCALL) &&
- addr == offsetof(struct compat_user, regs.gprs[2]))
- fixup_int_code(child, data);
+ addr == offsetof(struct compat_user, regs.gprs[2])) {
+ struct pt_regs *regs = task_pt_regs(child);
+
+ regs->int_code = 0x20000 | (data & 0xffff);
+ }
/* gpr 0-15 */
*(__u32*)((addr_t) ®s->psw + addr*2 + 4) = tmp;
}
}
#endif
-asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
-{
- unsigned long mask = -1UL;
- long ret = -1;
-
- if (is_compat_task())
- mask = 0xffffffff;
-
- /*
- * The sysc_tracesys code in entry.S stored the system
- * call number to gprs[2].
- */
- if (test_thread_flag(TIF_SYSCALL_TRACE) &&
- tracehook_report_syscall_entry(regs)) {
- /*
- * Tracing decided this syscall should not happen. Skip
- * the system call and the system call restart handling.
- */
- goto skip;
- }
-
-#ifdef CONFIG_SECCOMP
- /* Do the secure computing check after ptrace. */
- if (unlikely(test_thread_flag(TIF_SECCOMP))) {
- struct seccomp_data sd;
-
- if (is_compat_task()) {
- sd.instruction_pointer = regs->psw.addr & 0x7fffffff;
- sd.arch = AUDIT_ARCH_S390;
- } else {
- sd.instruction_pointer = regs->psw.addr;
- sd.arch = AUDIT_ARCH_S390X;
- }
-
- sd.nr = regs->int_code & 0xffff;
- sd.args[0] = regs->orig_gpr2 & mask;
- sd.args[1] = regs->gprs[3] & mask;
- sd.args[2] = regs->gprs[4] & mask;
- sd.args[3] = regs->gprs[5] & mask;
- sd.args[4] = regs->gprs[6] & mask;
- sd.args[5] = regs->gprs[7] & mask;
-
- if (__secure_computing(&sd) == -1)
- goto skip;
- }
-#endif /* CONFIG_SECCOMP */
-
- if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
- trace_sys_enter(regs, regs->int_code & 0xffff);
-
-
- audit_syscall_entry(regs->int_code & 0xffff, regs->orig_gpr2 & mask,
- regs->gprs[3] &mask, regs->gprs[4] &mask,
- regs->gprs[5] &mask);
-
- if ((signed long)regs->gprs[2] >= NR_syscalls) {
- regs->gprs[2] = -ENOSYS;
- ret = -ENOSYS;
- }
- return regs->gprs[2];
-skip:
- clear_pt_regs_flag(regs, PIF_SYSCALL);
- return ret;
-}
-
-asmlinkage void do_syscall_trace_exit(struct pt_regs *regs)
-{
- audit_syscall_exit(regs);
-
- if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
- trace_sys_exit(regs, regs->gprs[2]);
-
- if (test_thread_flag(TIF_SYSCALL_TRACE))
- tracehook_report_syscall_exit(regs, 0);
-}
-
/*
* user_regset definitions.
*/