root/arch/um/kernel/signal.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. block_signals_trace
  2. unblock_signals_trace
  3. um_trace_signals_on
  4. um_trace_signals_off
  5. handle_signal
  6. do_signal

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   4  */
   5 
   6 #include <linux/module.h>
   7 #include <linux/ptrace.h>
   8 #include <linux/sched.h>
   9 #include <linux/ftrace.h>
  10 #include <asm/siginfo.h>
  11 #include <asm/signal.h>
  12 #include <asm/unistd.h>
  13 #include <frame_kern.h>
  14 #include <kern_util.h>
  15 #include <os.h>
  16 
  17 EXPORT_SYMBOL(block_signals);
  18 EXPORT_SYMBOL(unblock_signals);
  19 
  20 void block_signals_trace(void)
  21 {
  22         block_signals();
  23         if (current_thread_info())
  24                 trace_hardirqs_off();
  25 }
  26 
  27 void unblock_signals_trace(void)
  28 {
  29         if (current_thread_info())
  30                 trace_hardirqs_on();
  31         unblock_signals();
  32 }
  33 
  34 void um_trace_signals_on(void)
  35 {
  36         if (current_thread_info())
  37                 trace_hardirqs_on();
  38 }
  39 
  40 void um_trace_signals_off(void)
  41 {
  42         if (current_thread_info())
  43                 trace_hardirqs_off();
  44 }
  45 
  46 /*
  47  * OK, we're invoking a handler
  48  */
  49 static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
  50 {
  51         sigset_t *oldset = sigmask_to_save();
  52         int singlestep = 0;
  53         unsigned long sp;
  54         int err;
  55 
  56         if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
  57                 singlestep = 1;
  58 
  59         /* Did we come from a system call? */
  60         if (PT_REGS_SYSCALL_NR(regs) >= 0) {
  61                 /* If so, check system call restarting.. */
  62                 switch (PT_REGS_SYSCALL_RET(regs)) {
  63                 case -ERESTART_RESTARTBLOCK:
  64                 case -ERESTARTNOHAND:
  65                         PT_REGS_SYSCALL_RET(regs) = -EINTR;
  66                         break;
  67 
  68                 case -ERESTARTSYS:
  69                         if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
  70                                 PT_REGS_SYSCALL_RET(regs) = -EINTR;
  71                                 break;
  72                         }
  73                 /* fallthrough */
  74                 case -ERESTARTNOINTR:
  75                         PT_REGS_RESTART_SYSCALL(regs);
  76                         PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
  77                         break;
  78                 }
  79         }
  80 
  81         sp = PT_REGS_SP(regs);
  82         if ((ksig->ka.sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
  83                 sp = current->sas_ss_sp + current->sas_ss_size;
  84 
  85 #ifdef CONFIG_ARCH_HAS_SC_SIGNALS
  86         if (!(ksig->ka.sa.sa_flags & SA_SIGINFO))
  87                 err = setup_signal_stack_sc(sp, ksig, regs, oldset);
  88         else
  89 #endif
  90                 err = setup_signal_stack_si(sp, ksig, regs, oldset);
  91 
  92         signal_setup_done(err, ksig, singlestep);
  93 }
  94 
  95 void do_signal(struct pt_regs *regs)
  96 {
  97         struct ksignal ksig;
  98         int handled_sig = 0;
  99 
 100         while (get_signal(&ksig)) {
 101                 handled_sig = 1;
 102                 /* Whee!  Actually deliver the signal.  */
 103                 handle_signal(&ksig, regs);
 104         }
 105 
 106         /* Did we come from a system call? */
 107         if (!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)) {
 108                 /* Restart the system call - no handlers present */
 109                 switch (PT_REGS_SYSCALL_RET(regs)) {
 110                 case -ERESTARTNOHAND:
 111                 case -ERESTARTSYS:
 112                 case -ERESTARTNOINTR:
 113                         PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
 114                         PT_REGS_RESTART_SYSCALL(regs);
 115                         break;
 116                 case -ERESTART_RESTARTBLOCK:
 117                         PT_REGS_ORIG_SYSCALL(regs) = __NR_restart_syscall;
 118                         PT_REGS_RESTART_SYSCALL(regs);
 119                         break;
 120                 }
 121         }
 122 
 123         /*
 124          * This closes a way to execute a system call on the host.  If
 125          * you set a breakpoint on a system call instruction and singlestep
 126          * from it, the tracing thread used to PTRACE_SINGLESTEP the process
 127          * rather than PTRACE_SYSCALL it, allowing the system call to execute
 128          * on the host.  The tracing thread will check this flag and
 129          * PTRACE_SYSCALL if necessary.
 130          */
 131         if (current->ptrace & PT_DTRACE)
 132                 current->thread.singlestep_syscall =
 133                         is_syscall(PT_REGS_IP(&current->thread.regs));
 134 
 135         /*
 136          * if there's no signal to deliver, we just put the saved sigmask
 137          * back
 138          */
 139         if (!handled_sig)
 140                 restore_saved_sigmask();
 141 }

/* [<][>][^][v][top][bottom][index][help] */