10d1fb0a4SAlex Dewar // SPDX-License-Identifier: GPL-2.0
21d3468a6SJeff Dike /*
3ba180fd4SJeff Dike * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
41d3468a6SJeff Dike */
51d3468a6SJeff Dike
6c5d4bb17SJeff Dike #include <linux/module.h>
7c5d4bb17SJeff Dike #include <linux/ptrace.h>
8c5d4bb17SJeff Dike #include <linux/sched.h>
90dafcbe1SJohannes Berg #include <linux/ftrace.h>
10c5d4bb17SJeff Dike #include <asm/siginfo.h>
11c5d4bb17SJeff Dike #include <asm/signal.h>
12c5d4bb17SJeff Dike #include <asm/unistd.h>
1337185b33SAl Viro #include <frame_kern.h>
1437185b33SAl Viro #include <kern_util.h>
150dafcbe1SJohannes Berg #include <os.h>
161d3468a6SJeff Dike
171d3468a6SJeff Dike EXPORT_SYMBOL(block_signals);
181d3468a6SJeff Dike EXPORT_SYMBOL(unblock_signals);
191d3468a6SJeff Dike
block_signals_trace(void)200dafcbe1SJohannes Berg void block_signals_trace(void)
210dafcbe1SJohannes Berg {
220dafcbe1SJohannes Berg block_signals();
230dafcbe1SJohannes Berg if (current_thread_info())
240dafcbe1SJohannes Berg trace_hardirqs_off();
250dafcbe1SJohannes Berg }
260dafcbe1SJohannes Berg
unblock_signals_trace(void)270dafcbe1SJohannes Berg void unblock_signals_trace(void)
280dafcbe1SJohannes Berg {
290dafcbe1SJohannes Berg if (current_thread_info())
300dafcbe1SJohannes Berg trace_hardirqs_on();
310dafcbe1SJohannes Berg unblock_signals();
320dafcbe1SJohannes Berg }
330dafcbe1SJohannes Berg
um_trace_signals_on(void)340dafcbe1SJohannes Berg void um_trace_signals_on(void)
350dafcbe1SJohannes Berg {
360dafcbe1SJohannes Berg if (current_thread_info())
370dafcbe1SJohannes Berg trace_hardirqs_on();
380dafcbe1SJohannes Berg }
390dafcbe1SJohannes Berg
um_trace_signals_off(void)400dafcbe1SJohannes Berg void um_trace_signals_off(void)
410dafcbe1SJohannes Berg {
420dafcbe1SJohannes Berg if (current_thread_info())
430dafcbe1SJohannes Berg trace_hardirqs_off();
440dafcbe1SJohannes Berg }
450dafcbe1SJohannes Berg
461d3468a6SJeff Dike /*
471d3468a6SJeff Dike * OK, we're invoking a handler
481d3468a6SJeff Dike */
handle_signal(struct ksignal * ksig,struct pt_regs * regs)49307627eeSRichard Weinberger static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
501d3468a6SJeff Dike {
51b7f9a11aSAl Viro sigset_t *oldset = sigmask_to_save();
52f9a38eacSAl Viro int singlestep = 0;
531d3468a6SJeff Dike unsigned long sp;
541d3468a6SJeff Dike int err;
551d3468a6SJeff Dike
56*c200e4bbSEric W. Biederman if (test_thread_flag(TIF_SINGLESTEP) && (current->ptrace & PT_PTRACED))
57f9a38eacSAl Viro singlestep = 1;
58f9a38eacSAl Viro
591d3468a6SJeff Dike /* Did we come from a system call? */
601d3468a6SJeff Dike if (PT_REGS_SYSCALL_NR(regs) >= 0) {
611d3468a6SJeff Dike /* If so, check system call restarting.. */
621d3468a6SJeff Dike switch (PT_REGS_SYSCALL_RET(regs)) {
631d3468a6SJeff Dike case -ERESTART_RESTARTBLOCK:
641d3468a6SJeff Dike case -ERESTARTNOHAND:
651d3468a6SJeff Dike PT_REGS_SYSCALL_RET(regs) = -EINTR;
661d3468a6SJeff Dike break;
671d3468a6SJeff Dike
681d3468a6SJeff Dike case -ERESTARTSYS:
69307627eeSRichard Weinberger if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
701d3468a6SJeff Dike PT_REGS_SYSCALL_RET(regs) = -EINTR;
711d3468a6SJeff Dike break;
721d3468a6SJeff Dike }
73df561f66SGustavo A. R. Silva fallthrough;
741d3468a6SJeff Dike case -ERESTARTNOINTR:
751d3468a6SJeff Dike PT_REGS_RESTART_SYSCALL(regs);
761d3468a6SJeff Dike PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
771d3468a6SJeff Dike break;
781d3468a6SJeff Dike }
791d3468a6SJeff Dike }
801d3468a6SJeff Dike
811d3468a6SJeff Dike sp = PT_REGS_SP(regs);
82307627eeSRichard Weinberger if ((ksig->ka.sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
831d3468a6SJeff Dike sp = current->sas_ss_sp + current->sas_ss_size;
841d3468a6SJeff Dike
851d3468a6SJeff Dike #ifdef CONFIG_ARCH_HAS_SC_SIGNALS
86307627eeSRichard Weinberger if (!(ksig->ka.sa.sa_flags & SA_SIGINFO))
87307627eeSRichard Weinberger err = setup_signal_stack_sc(sp, ksig, regs, oldset);
881d3468a6SJeff Dike else
891d3468a6SJeff Dike #endif
90307627eeSRichard Weinberger err = setup_signal_stack_si(sp, ksig, regs, oldset);
911d3468a6SJeff Dike
92307627eeSRichard Weinberger signal_setup_done(err, ksig, singlestep);
931d3468a6SJeff Dike }
941d3468a6SJeff Dike
do_signal(struct pt_regs * regs)95ccaee5f8SIngo Molnar void do_signal(struct pt_regs *regs)
961d3468a6SJeff Dike {
97307627eeSRichard Weinberger struct ksignal ksig;
98307627eeSRichard Weinberger int handled_sig = 0;
991d3468a6SJeff Dike
100322740efSRichard Weinberger while (get_signal(&ksig)) {
1011d3468a6SJeff Dike handled_sig = 1;
1021d3468a6SJeff Dike /* Whee! Actually deliver the signal. */
103307627eeSRichard Weinberger handle_signal(&ksig, regs);
1041d3468a6SJeff Dike }
1051d3468a6SJeff Dike
1061d3468a6SJeff Dike /* Did we come from a system call? */
1071d3468a6SJeff Dike if (!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)) {
1081d3468a6SJeff Dike /* Restart the system call - no handlers present */
1091d3468a6SJeff Dike switch (PT_REGS_SYSCALL_RET(regs)) {
1101d3468a6SJeff Dike case -ERESTARTNOHAND:
1111d3468a6SJeff Dike case -ERESTARTSYS:
1121d3468a6SJeff Dike case -ERESTARTNOINTR:
1131d3468a6SJeff Dike PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
1141d3468a6SJeff Dike PT_REGS_RESTART_SYSCALL(regs);
1151d3468a6SJeff Dike break;
1161d3468a6SJeff Dike case -ERESTART_RESTARTBLOCK:
1171d3468a6SJeff Dike PT_REGS_ORIG_SYSCALL(regs) = __NR_restart_syscall;
1181d3468a6SJeff Dike PT_REGS_RESTART_SYSCALL(regs);
1191d3468a6SJeff Dike break;
1201d3468a6SJeff Dike }
1211d3468a6SJeff Dike }
1221d3468a6SJeff Dike
123ba180fd4SJeff Dike /*
124ba180fd4SJeff Dike * This closes a way to execute a system call on the host. If
1251d3468a6SJeff Dike * you set a breakpoint on a system call instruction and singlestep
1261d3468a6SJeff Dike * from it, the tracing thread used to PTRACE_SINGLESTEP the process
1271d3468a6SJeff Dike * rather than PTRACE_SYSCALL it, allowing the system call to execute
1281d3468a6SJeff Dike * on the host. The tracing thread will check this flag and
1291d3468a6SJeff Dike * PTRACE_SYSCALL if necessary.
1301d3468a6SJeff Dike */
131*c200e4bbSEric W. Biederman if (test_thread_flag(TIF_SINGLESTEP))
1321d3468a6SJeff Dike current->thread.singlestep_syscall =
1331d3468a6SJeff Dike is_syscall(PT_REGS_IP(¤t->thread.regs));
1341d3468a6SJeff Dike
135ba180fd4SJeff Dike /*
136ba180fd4SJeff Dike * if there's no signal to deliver, we just put the saved sigmask
137ba180fd4SJeff Dike * back
138ba180fd4SJeff Dike */
13951a7b448SAl Viro if (!handled_sig)
14051a7b448SAl Viro restore_saved_sigmask();
1411d3468a6SJeff Dike }
142