cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

signal.c (9505B)


      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
     23void (*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
     33static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
     34{
     35	struct uml_pt_regs r;
     36	int save_errno = errno;
     37
     38	r.is_user = 0;
     39	if (sig == SIGSEGV) {
     40		/* For segfaults, we want the data from the sigcontext. */
     41		get_regs_from_mc(&r, mc);
     42		GET_FAULTINFO_FROM_MC(r.faultinfo, mc);
     43	}
     44
     45	/* enable signals if sig isn't IRQ signal */
     46	if ((sig != SIGIO) && (sig != SIGWINCH))
     47		unblock_signals_trace();
     48
     49	(*sig_info[sig])(sig, si, &r);
     50
     51	errno = save_errno;
     52}
     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
     66int signals_enabled;
     67#ifdef UML_CONFIG_UML_TIME_TRAVEL_SUPPORT
     68static int signals_blocked;
     69#else
     70#define signals_blocked 0
     71#endif
     72static unsigned int signals_pending;
     73static unsigned int signals_active = 0;
     74
     75void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
     76{
     77	int enabled = signals_enabled;
     78
     79	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			signals_pending |= SIGIO_MASK;
     90		return;
     91	}
     92
     93	block_signals_trace();
     94
     95	sig_handler_common(sig, si, mc);
     96
     97	um_set_signals_trace(enabled);
     98}
     99
    100static void timer_real_alarm_handler(mcontext_t *mc)
    101{
    102	struct uml_pt_regs regs;
    103
    104	if (mc != NULL)
    105		get_regs_from_mc(&regs, mc);
    106	else
    107		memset(&regs, 0, sizeof(regs));
    108	timer_handler(SIGALRM, NULL, &regs);
    109}
    110
    111void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
    112{
    113	int enabled;
    114
    115	enabled = signals_enabled;
    116	if (!signals_enabled) {
    117		signals_pending |= SIGALRM_MASK;
    118		return;
    119	}
    120
    121	block_signals_trace();
    122
    123	signals_active |= SIGALRM_MASK;
    124
    125	timer_real_alarm_handler(mc);
    126
    127	signals_active &= ~SIGALRM_MASK;
    128
    129	um_set_signals_trace(enabled);
    130}
    131
    132void deliver_alarm(void) {
    133    timer_alarm_handler(SIGALRM, NULL, NULL);
    134}
    135
    136void timer_set_signal_handler(void)
    137{
    138	set_handler(SIGALRM);
    139}
    140
    141void set_sigstack(void *sig_stack, int size)
    142{
    143	stack_t stack = {
    144		.ss_flags = 0,
    145		.ss_sp = sig_stack,
    146		.ss_size = size
    147	};
    148
    149	if (sigaltstack(&stack, NULL) != 0)
    150		panic("enabling signal stack failed, errno = %d\n", errno);
    151}
    152
    153static void sigusr1_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
    154{
    155	uml_pm_wake();
    156}
    157
    158void register_pm_wake_signal(void)
    159{
    160	set_handler(SIGUSR1);
    161}
    162
    163static 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
    177static void hard_handler(int sig, siginfo_t *si, void *p)
    178{
    179	ucontext_t *uc = p;
    180	mcontext_t *mc = &uc->uc_mcontext;
    181	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		bail = to_irq_stack(&pending);
    197		if (bail)
    198			return;
    199
    200		nested = pending & 1;
    201		pending &= ~1;
    202
    203		while ((sig = ffs(pending)) != 0){
    204			sig--;
    205			pending &= ~(1 << sig);
    206			(*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		if (!nested)
    216			pending = from_irq_stack(nested);
    217	} while (pending);
    218}
    219
    220void set_handler(int sig)
    221{
    222	struct sigaction action;
    223	int flags = SA_SIGINFO | SA_ONSTACK;
    224	sigset_t sig_mask;
    225
    226	action.sa_sigaction = hard_handler;
    227
    228	/* block irq ones */
    229	sigemptyset(&action.sa_mask);
    230	sigaddset(&action.sa_mask, SIGIO);
    231	sigaddset(&action.sa_mask, SIGWINCH);
    232	sigaddset(&action.sa_mask, SIGALRM);
    233
    234	if (sig == SIGSEGV)
    235		flags |= SA_NODEFER;
    236
    237	if (sigismember(&action.sa_mask, sig))
    238		flags |= SA_RESTART; /* if it's an irq signal */
    239
    240	action.sa_flags = flags;
    241	action.sa_restorer = NULL;
    242	if (sigaction(sig, &action, NULL) < 0)
    243		panic("sigaction failed - errno = %d\n", errno);
    244
    245	sigemptyset(&sig_mask);
    246	sigaddset(&sig_mask, sig);
    247	if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0)
    248		panic("sigprocmask failed - errno = %d\n", errno);
    249}
    250
    251void send_sigio_to_self(void)
    252{
    253	kill(os_getpid(), SIGIO);
    254}
    255
    256int change_sig(int signal, int on)
    257{
    258	sigset_t sigset;
    259
    260	sigemptyset(&sigset);
    261	sigaddset(&sigset, signal);
    262	if (sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, NULL) < 0)
    263		return -errno;
    264
    265	return 0;
    266}
    267
    268void block_signals(void)
    269{
    270	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	barrier();
    278}
    279
    280void unblock_signals(void)
    281{
    282	int save_pending;
    283
    284	if (signals_enabled == 1)
    285		return;
    286
    287	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		barrier();
    306
    307		save_pending = signals_pending;
    308		if (save_pending == 0)
    309			return;
    310
    311		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		signals_enabled = 0;
    322		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		if (save_pending & SIGIO_MASK)
    333			sig_handler_common(SIGIO, NULL, NULL);
    334
    335		/* Do not reenter the handler */
    336
    337		if ((save_pending & SIGALRM_MASK) && (!(signals_active & SIGALRM_MASK)))
    338			timer_real_alarm_handler(NULL);
    339
    340		/* Rerun the loop only if there is still pending SIGIO and not in TIMER handler */
    341
    342		if (!(signals_pending & SIGIO_MASK) && (signals_active & SIGALRM_MASK))
    343			return;
    344
    345		/* Re-enable signals and trace that we're doing so. */
    346		um_trace_signals_on();
    347		signals_enabled = 1;
    348	}
    349}
    350
    351int um_set_signals(int enable)
    352{
    353	int ret;
    354	if (signals_enabled == enable)
    355		return enable;
    356
    357	ret = signals_enabled;
    358	if (enable)
    359		unblock_signals();
    360	else block_signals();
    361
    362	return ret;
    363}
    364
    365int um_set_signals_trace(int enable)
    366{
    367	int ret;
    368	if (signals_enabled == enable)
    369		return enable;
    370
    371	ret = signals_enabled;
    372	if (enable)
    373		unblock_signals_trace();
    374	else
    375		block_signals_trace();
    376
    377	return ret;
    378}
    379
    380#ifdef UML_CONFIG_UML_TIME_TRAVEL_SUPPORT
    381void mark_sigio_pending(void)
    382{
    383	signals_pending |= SIGIO_MASK;
    384}
    385
    386void block_signals_hard(void)
    387{
    388	if (signals_blocked)
    389		return;
    390	signals_blocked = 1;
    391	barrier();
    392}
    393
    394void 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
    413int os_is_signal_stack(void)
    414{
    415	stack_t ss;
    416	sigaltstack(NULL, &ss);
    417
    418	return ss.ss_flags & SS_ONSTACK;
    419}