Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
0004  */
0005 
0006 #include <linux/module.h>
0007 #include <linux/ptrace.h>
0008 #include <linux/sched.h>
0009 #include <linux/ftrace.h>
0010 #include <asm/siginfo.h>
0011 #include <asm/signal.h>
0012 #include <asm/unistd.h>
0013 #include <frame_kern.h>
0014 #include <kern_util.h>
0015 #include <os.h>
0016 
0017 EXPORT_SYMBOL(block_signals);
0018 EXPORT_SYMBOL(unblock_signals);
0019 
0020 void block_signals_trace(void)
0021 {
0022     block_signals();
0023     if (current_thread_info())
0024         trace_hardirqs_off();
0025 }
0026 
0027 void unblock_signals_trace(void)
0028 {
0029     if (current_thread_info())
0030         trace_hardirqs_on();
0031     unblock_signals();
0032 }
0033 
0034 void um_trace_signals_on(void)
0035 {
0036     if (current_thread_info())
0037         trace_hardirqs_on();
0038 }
0039 
0040 void um_trace_signals_off(void)
0041 {
0042     if (current_thread_info())
0043         trace_hardirqs_off();
0044 }
0045 
0046 /*
0047  * OK, we're invoking a handler
0048  */
0049 static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
0050 {
0051     sigset_t *oldset = sigmask_to_save();
0052     int singlestep = 0;
0053     unsigned long sp;
0054     int err;
0055 
0056     if (test_thread_flag(TIF_SINGLESTEP) && (current->ptrace & PT_PTRACED))
0057         singlestep = 1;
0058 
0059     /* Did we come from a system call? */
0060     if (PT_REGS_SYSCALL_NR(regs) >= 0) {
0061         /* If so, check system call restarting.. */
0062         switch (PT_REGS_SYSCALL_RET(regs)) {
0063         case -ERESTART_RESTARTBLOCK:
0064         case -ERESTARTNOHAND:
0065             PT_REGS_SYSCALL_RET(regs) = -EINTR;
0066             break;
0067 
0068         case -ERESTARTSYS:
0069             if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
0070                 PT_REGS_SYSCALL_RET(regs) = -EINTR;
0071                 break;
0072             }
0073             fallthrough;
0074         case -ERESTARTNOINTR:
0075             PT_REGS_RESTART_SYSCALL(regs);
0076             PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
0077             break;
0078         }
0079     }
0080 
0081     sp = PT_REGS_SP(regs);
0082     if ((ksig->ka.sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
0083         sp = current->sas_ss_sp + current->sas_ss_size;
0084 
0085 #ifdef CONFIG_ARCH_HAS_SC_SIGNALS
0086     if (!(ksig->ka.sa.sa_flags & SA_SIGINFO))
0087         err = setup_signal_stack_sc(sp, ksig, regs, oldset);
0088     else
0089 #endif
0090         err = setup_signal_stack_si(sp, ksig, regs, oldset);
0091 
0092     signal_setup_done(err, ksig, singlestep);
0093 }
0094 
0095 void do_signal(struct pt_regs *regs)
0096 {
0097     struct ksignal ksig;
0098     int handled_sig = 0;
0099 
0100     while (get_signal(&ksig)) {
0101         handled_sig = 1;
0102         /* Whee!  Actually deliver the signal.  */
0103         handle_signal(&ksig, regs);
0104     }
0105 
0106     /* Did we come from a system call? */
0107     if (!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)) {
0108         /* Restart the system call - no handlers present */
0109         switch (PT_REGS_SYSCALL_RET(regs)) {
0110         case -ERESTARTNOHAND:
0111         case -ERESTARTSYS:
0112         case -ERESTARTNOINTR:
0113             PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
0114             PT_REGS_RESTART_SYSCALL(regs);
0115             break;
0116         case -ERESTART_RESTARTBLOCK:
0117             PT_REGS_ORIG_SYSCALL(regs) = __NR_restart_syscall;
0118             PT_REGS_RESTART_SYSCALL(regs);
0119             break;
0120         }
0121     }
0122 
0123     /*
0124      * This closes a way to execute a system call on the host.  If
0125      * you set a breakpoint on a system call instruction and singlestep
0126      * from it, the tracing thread used to PTRACE_SINGLESTEP the process
0127      * rather than PTRACE_SYSCALL it, allowing the system call to execute
0128      * on the host.  The tracing thread will check this flag and
0129      * PTRACE_SYSCALL if necessary.
0130      */
0131     if (test_thread_flag(TIF_SINGLESTEP))
0132         current->thread.singlestep_syscall =
0133             is_syscall(PT_REGS_IP(&current->thread.regs));
0134 
0135     /*
0136      * if there's no signal to deliver, we just put the saved sigmask
0137      * back
0138      */
0139     if (!handled_sig)
0140         restore_saved_sigmask();
0141 }