LCOV - code coverage report
Current view: top level - arch/um/os-Linux - signal.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 83 130 63.8 %
Date: 2023-08-24 13:40:31 Functions: 13 18 72.2 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (C) 2015 Anton Ivanov (aivanov@{brocade.com,kot-begemot.co.uk})
       4             :  * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
       5             :  * Copyright (C) 2004 PathScale, Inc
       6             :  * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
       7             :  */
       8             : 
       9             : #include <stdlib.h>
      10             : #include <stdarg.h>
      11             : #include <errno.h>
      12             : #include <signal.h>
      13             : #include <string.h>
      14             : #include <strings.h>
      15             : #include <as-layout.h>
      16             : #include <kern_util.h>
      17             : #include <os.h>
      18             : #include <sysdep/mcontext.h>
      19             : #include <um_malloc.h>
      20             : #include <sys/ucontext.h>
      21             : #include <timetravel.h>
      22             : 
      23             : void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = {
      24             :         [SIGTRAP]       = relay_signal,
      25             :         [SIGFPE]        = relay_signal,
      26             :         [SIGILL]        = relay_signal,
      27             :         [SIGWINCH]      = winch,
      28             :         [SIGBUS]        = bus_handler,
      29             :         [SIGSEGV]       = segv_handler,
      30             :         [SIGIO]         = sigio_handler,
      31             : };
      32             : 
      33           0 : static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
      34             : {
      35             :         struct uml_pt_regs r;
      36           0 :         int save_errno = errno;
      37             : 
      38           0 :         r.is_user = 0;
      39           0 :         if (sig == SIGSEGV) {
      40             :                 /* For segfaults, we want the data from the sigcontext. */
      41           0 :                 get_regs_from_mc(&r, mc);
      42           0 :                 GET_FAULTINFO_FROM_MC(r.faultinfo, mc);
      43             :         }
      44             : 
      45             :         /* enable signals if sig isn't IRQ signal */
      46           0 :         if ((sig != SIGIO) && (sig != SIGWINCH))
      47           0 :                 unblock_signals_trace();
      48             : 
      49           0 :         (*sig_info[sig])(sig, si, &r);
      50             : 
      51           0 :         errno = save_errno;
      52           0 : }
      53             : 
      54             : /*
      55             :  * These are the asynchronous signals.  SIGPROF is excluded because we want to
      56             :  * be able to profile all of UML, not just the non-critical sections.  If
      57             :  * profiling is not thread-safe, then that is not my problem.  We can disable
      58             :  * profiling when SMP is enabled in that case.
      59             :  */
      60             : #define SIGIO_BIT 0
      61             : #define SIGIO_MASK (1 << SIGIO_BIT)
      62             : 
      63             : #define SIGALRM_BIT 1
      64             : #define SIGALRM_MASK (1 << SIGALRM_BIT)
      65             : 
      66             : int signals_enabled;
      67             : #ifdef UML_CONFIG_UML_TIME_TRAVEL_SUPPORT
      68             : static int signals_blocked;
      69             : #else
      70             : #define signals_blocked 0
      71             : #endif
      72             : static unsigned int signals_pending;
      73             : static unsigned int signals_active = 0;
      74             : 
      75           0 : void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
      76             : {
      77           0 :         int enabled = signals_enabled;
      78             : 
      79           0 :         if ((signals_blocked || !enabled) && (sig == SIGIO)) {
      80             :                 /*
      81             :                  * In TT_MODE_EXTERNAL, need to still call time-travel
      82             :                  * handlers unless signals are also blocked for the
      83             :                  * external time message processing. This will mark
      84             :                  * signals_pending by itself (only if necessary.)
      85             :                  */
      86             :                 if (!signals_blocked && time_travel_mode == TT_MODE_EXTERNAL)
      87             :                         sigio_run_timetravel_handlers();
      88             :                 else
      89           0 :                         signals_pending |= SIGIO_MASK;
      90           0 :                 return;
      91             :         }
      92             : 
      93           0 :         block_signals_trace();
      94             : 
      95           0 :         sig_handler_common(sig, si, mc);
      96             : 
      97           0 :         um_set_signals_trace(enabled);
      98             : }
      99             : 
     100           5 : static void timer_real_alarm_handler(mcontext_t *mc)
     101             : {
     102             :         struct uml_pt_regs regs;
     103             : 
     104           5 :         if (mc != NULL)
     105           5 :                 get_regs_from_mc(&regs, mc);
     106             :         else
     107           0 :                 memset(&regs, 0, sizeof(regs));
     108           5 :         timer_handler(SIGALRM, NULL, &regs);
     109           5 : }
     110             : 
     111           5 : void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
     112             : {
     113             :         int enabled;
     114             : 
     115           5 :         enabled = signals_enabled;
     116           5 :         if (!signals_enabled) {
     117           0 :                 signals_pending |= SIGALRM_MASK;
     118           0 :                 return;
     119             :         }
     120             : 
     121           5 :         block_signals_trace();
     122             : 
     123           5 :         signals_active |= SIGALRM_MASK;
     124             : 
     125           5 :         timer_real_alarm_handler(mc);
     126             : 
     127           5 :         signals_active &= ~SIGALRM_MASK;
     128             : 
     129           5 :         um_set_signals_trace(enabled);
     130             : }
     131             : 
     132           0 : void deliver_alarm(void) {
     133           0 :     timer_alarm_handler(SIGALRM, NULL, NULL);
     134           0 : }
     135             : 
     136           1 : void timer_set_signal_handler(void)
     137             : {
     138           1 :         set_handler(SIGALRM);
     139           1 : }
     140             : 
     141           1 : void set_sigstack(void *sig_stack, int size)
     142             : {
     143           1 :         stack_t stack = {
     144             :                 .ss_flags = 0,
     145             :                 .ss_sp = sig_stack,
     146             :                 .ss_size = size
     147             :         };
     148             : 
     149           1 :         if (sigaltstack(&stack, NULL) != 0)
     150           0 :                 panic("enabling signal stack failed, errno = %d\n", errno);
     151           1 : }
     152             : 
     153           0 : static void sigusr1_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
     154             : {
     155           0 :         uml_pm_wake();
     156           0 : }
     157             : 
     158           1 : void register_pm_wake_signal(void)
     159             : {
     160           1 :         set_handler(SIGUSR1);
     161           1 : }
     162             : 
     163             : static void (*handlers[_NSIG])(int sig, struct siginfo *si, mcontext_t *mc) = {
     164             :         [SIGSEGV] = sig_handler,
     165             :         [SIGBUS] = sig_handler,
     166             :         [SIGILL] = sig_handler,
     167             :         [SIGFPE] = sig_handler,
     168             :         [SIGTRAP] = sig_handler,
     169             : 
     170             :         [SIGIO] = sig_handler,
     171             :         [SIGWINCH] = sig_handler,
     172             :         [SIGALRM] = timer_alarm_handler,
     173             : 
     174             :         [SIGUSR1] = sigusr1_handler,
     175             : };
     176             : 
     177           5 : static void hard_handler(int sig, siginfo_t *si, void *p)
     178             : {
     179           5 :         ucontext_t *uc = p;
     180           5 :         mcontext_t *mc = &uc->uc_mcontext;
     181           5 :         unsigned long pending = 1UL << sig;
     182             : 
     183             :         do {
     184             :                 int nested, bail;
     185             : 
     186             :                 /*
     187             :                  * pending comes back with one bit set for each
     188             :                  * interrupt that arrived while setting up the stack,
     189             :                  * plus a bit for this interrupt, plus the zero bit is
     190             :                  * set if this is a nested interrupt.
     191             :                  * If bail is true, then we interrupted another
     192             :                  * handler setting up the stack.  In this case, we
     193             :                  * have to return, and the upper handler will deal
     194             :                  * with this interrupt.
     195             :                  */
     196           5 :                 bail = to_irq_stack(&pending);
     197           5 :                 if (bail)
     198           0 :                         return;
     199             : 
     200           5 :                 nested = pending & 1;
     201           5 :                 pending &= ~1;
     202             : 
     203          15 :                 while ((sig = ffs(pending)) != 0){
     204           5 :                         sig--;
     205           5 :                         pending &= ~(1 << sig);
     206           5 :                         (*handlers[sig])(sig, (struct siginfo *)si, mc);
     207             :                 }
     208             : 
     209             :                 /*
     210             :                  * Again, pending comes back with a mask of signals
     211             :                  * that arrived while tearing down the stack.  If this
     212             :                  * is non-zero, we just go back, set up the stack
     213             :                  * again, and handle the new interrupts.
     214             :                  */
     215           5 :                 if (!nested)
     216           5 :                         pending = from_irq_stack(nested);
     217           5 :         } while (pending);
     218             : }
     219             : 
     220           9 : void set_handler(int sig)
     221             : {
     222             :         struct sigaction action;
     223           9 :         int flags = SA_SIGINFO | SA_ONSTACK;
     224             :         sigset_t sig_mask;
     225             : 
     226           9 :         action.sa_sigaction = hard_handler;
     227             : 
     228             :         /* block irq ones */
     229           9 :         sigemptyset(&action.sa_mask);
     230           9 :         sigaddset(&action.sa_mask, SIGIO);
     231           9 :         sigaddset(&action.sa_mask, SIGWINCH);
     232           9 :         sigaddset(&action.sa_mask, SIGALRM);
     233             : 
     234           9 :         if (sig == SIGSEGV)
     235           1 :                 flags |= SA_NODEFER;
     236             : 
     237           9 :         if (sigismember(&action.sa_mask, sig))
     238           3 :                 flags |= SA_RESTART; /* if it's an irq signal */
     239             : 
     240           9 :         action.sa_flags = flags;
     241           9 :         action.sa_restorer = NULL;
     242           9 :         if (sigaction(sig, &action, NULL) < 0)
     243           0 :                 panic("sigaction failed - errno = %d\n", errno);
     244             : 
     245           9 :         sigemptyset(&sig_mask);
     246           9 :         sigaddset(&sig_mask, sig);
     247           9 :         if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0)
     248           0 :                 panic("sigprocmask failed - errno = %d\n", errno);
     249           9 : }
     250             : 
     251           0 : void send_sigio_to_self(void)
     252             : {
     253           0 :         kill(os_getpid(), SIGIO);
     254           0 : }
     255             : 
     256          10 : int change_sig(int signal, int on)
     257             : {
     258             :         sigset_t sigset;
     259             : 
     260          10 :         sigemptyset(&sigset);
     261          10 :         sigaddset(&sigset, signal);
     262          10 :         if (sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, NULL) < 0)
     263           0 :                 return -errno;
     264             : 
     265             :         return 0;
     266             : }
     267             : 
     268        4677 : void block_signals(void)
     269             : {
     270       34143 :         signals_enabled = 0;
     271             :         /*
     272             :          * This must return with signals disabled, so this barrier
     273             :          * ensures that writes are flushed out before the return.
     274             :          * This might matter if gcc figures out how to inline this and
     275             :          * decides to shuffle this code into the caller.
     276             :          */
     277       34143 :         barrier();
     278        4677 : }
     279             : 
     280       34142 : void unblock_signals(void)
     281             : {
     282             :         int save_pending;
     283             : 
     284       34142 :         if (signals_enabled == 1)
     285             :                 return;
     286             : 
     287       34142 :         signals_enabled = 1;
     288             : #ifdef UML_CONFIG_UML_TIME_TRAVEL_SUPPORT
     289             :         deliver_time_travel_irqs();
     290             : #endif
     291             : 
     292             :         /*
     293             :          * We loop because the IRQ handler returns with interrupts off.  So,
     294             :          * interrupts may have arrived and we need to re-enable them and
     295             :          * recheck signals_pending.
     296             :          */
     297             :         while (1) {
     298             :                 /*
     299             :                  * Save and reset save_pending after enabling signals.  This
     300             :                  * way, signals_pending won't be changed while we're reading it.
     301             :                  *
     302             :                  * Setting signals_enabled and reading signals_pending must
     303             :                  * happen in this order, so have the barrier here.
     304             :                  */
     305       34142 :                 barrier();
     306             : 
     307       34142 :                 save_pending = signals_pending;
     308       34142 :                 if (save_pending == 0)
     309             :                         return;
     310             : 
     311           0 :                 signals_pending = 0;
     312             : 
     313             :                 /*
     314             :                  * We have pending interrupts, so disable signals, as the
     315             :                  * handlers expect them off when they are called.  They will
     316             :                  * be enabled again above. We need to trace this, as we're
     317             :                  * expected to be enabling interrupts already, but any more
     318             :                  * tracing that happens inside the handlers we call for the
     319             :                  * pending signals will mess up the tracing state.
     320             :                  */
     321           0 :                 signals_enabled = 0;
     322           0 :                 um_trace_signals_off();
     323             : 
     324             :                 /*
     325             :                  * Deal with SIGIO first because the alarm handler might
     326             :                  * schedule, leaving the pending SIGIO stranded until we come
     327             :                  * back here.
     328             :                  *
     329             :                  * SIGIO's handler doesn't use siginfo or mcontext,
     330             :                  * so they can be NULL.
     331             :                  */
     332           0 :                 if (save_pending & SIGIO_MASK)
     333           0 :                         sig_handler_common(SIGIO, NULL, NULL);
     334             : 
     335             :                 /* Do not reenter the handler */
     336             : 
     337           0 :                 if ((save_pending & SIGALRM_MASK) && (!(signals_active & SIGALRM_MASK)))
     338           0 :                         timer_real_alarm_handler(NULL);
     339             : 
     340             :                 /* Rerun the loop only if there is still pending SIGIO and not in TIMER handler */
     341             : 
     342           0 :                 if (!(signals_pending & SIGIO_MASK) && (signals_active & SIGALRM_MASK))
     343             :                         return;
     344             : 
     345             :                 /* Re-enable signals and trace that we're doing so. */
     346           0 :                 um_trace_signals_on();
     347           0 :                 signals_enabled = 1;
     348             :         }
     349             : }
     350             : 
     351       73806 : int um_set_signals(int enable)
     352             : {
     353             :         int ret;
     354       73806 :         if (signals_enabled == enable)
     355             :                 return enable;
     356             : 
     357       58932 :         ret = signals_enabled;
     358       58932 :         if (enable)
     359       29466 :                 unblock_signals();
     360             :         else block_signals();
     361             : 
     362             :         return ret;
     363             : }
     364             : 
     365         862 : int um_set_signals_trace(int enable)
     366             : {
     367             :         int ret;
     368         862 :         if (signals_enabled == enable)
     369             :                 return enable;
     370             : 
     371           5 :         ret = signals_enabled;
     372           5 :         if (enable)
     373           5 :                 unblock_signals_trace();
     374             :         else
     375           0 :                 block_signals_trace();
     376             : 
     377             :         return ret;
     378             : }
     379             : 
     380             : #ifdef UML_CONFIG_UML_TIME_TRAVEL_SUPPORT
     381             : void mark_sigio_pending(void)
     382             : {
     383             :         signals_pending |= SIGIO_MASK;
     384             : }
     385             : 
     386             : void block_signals_hard(void)
     387             : {
     388             :         if (signals_blocked)
     389             :                 return;
     390             :         signals_blocked = 1;
     391             :         barrier();
     392             : }
     393             : 
     394             : void unblock_signals_hard(void)
     395             : {
     396             :         if (!signals_blocked)
     397             :                 return;
     398             :         /* Must be set to 0 before we check the pending bits etc. */
     399             :         signals_blocked = 0;
     400             :         barrier();
     401             : 
     402             :         if (signals_pending && signals_enabled) {
     403             :                 /* this is a bit inefficient, but that's not really important */
     404             :                 block_signals();
     405             :                 unblock_signals();
     406             :         } else if (signals_pending & SIGIO_MASK) {
     407             :                 /* we need to run time-travel handlers even if not enabled */
     408             :                 sigio_run_timetravel_handlers();
     409             :         }
     410             : }
     411             : #endif
     412             : 
     413           1 : int os_is_signal_stack(void)
     414             : {
     415             :         stack_t ss;
     416           1 :         sigaltstack(NULL, &ss);
     417             : 
     418           1 :         return ss.ss_flags & SS_ONSTACK;
     419             : }

Generated by: LCOV version 1.14