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 (8534B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * OpenRISC signal.c
      4 *
      5 * Linux architectural port borrowing liberally from similar works of
      6 * others.  All original copyrights apply as per the original source
      7 * declaration.
      8 *
      9 * Modifications for the OpenRISC architecture:
     10 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
     11 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
     12 */
     13
     14#include <linux/sched.h>
     15#include <linux/mm.h>
     16#include <linux/smp.h>
     17#include <linux/kernel.h>
     18#include <linux/signal.h>
     19#include <linux/errno.h>
     20#include <linux/wait.h>
     21#include <linux/ptrace.h>
     22#include <linux/unistd.h>
     23#include <linux/stddef.h>
     24#include <linux/resume_user_mode.h>
     25
     26#include <asm/processor.h>
     27#include <asm/syscall.h>
     28#include <asm/ucontext.h>
     29#include <linux/uaccess.h>
     30
     31struct rt_sigframe {
     32	struct siginfo info;
     33	struct ucontext uc;
     34	unsigned char retcode[16];	/* trampoline code */
     35};
     36
     37static int restore_sigcontext(struct pt_regs *regs,
     38			      struct sigcontext __user *sc)
     39{
     40	int err = 0;
     41
     42	/* Always make any pending restarted system calls return -EINTR */
     43	current->restart_block.fn = do_no_restart_syscall;
     44
     45	/*
     46	 * Restore the regs from &sc->regs.
     47	 * (sc is already checked since the sigframe was
     48	 *  checked in sys_sigreturn previously)
     49	 */
     50	err |= __copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long));
     51	err |= __copy_from_user(&regs->pc, &sc->regs.pc, sizeof(unsigned long));
     52	err |= __copy_from_user(&regs->sr, &sc->regs.sr, sizeof(unsigned long));
     53
     54	/* make sure the SM-bit is cleared so user-mode cannot fool us */
     55	regs->sr &= ~SPR_SR_SM;
     56
     57	regs->orig_gpr11 = -1;	/* Avoid syscall restart checks */
     58
     59	/* TODO: the other ports use regs->orig_XX to disable syscall checks
     60	 * after this completes, but we don't use that mechanism. maybe we can
     61	 * use it now ?
     62	 */
     63
     64	return err;
     65}
     66
     67asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
     68{
     69	struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs->sp;
     70	sigset_t set;
     71
     72	/*
     73	 * Since we stacked the signal on a dword boundary,
     74	 * then frame should be dword aligned here.  If it's
     75	 * not, then the user is trying to mess with us.
     76	 */
     77	if (((unsigned long)frame) & 3)
     78		goto badframe;
     79
     80	if (!access_ok(frame, sizeof(*frame)))
     81		goto badframe;
     82	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
     83		goto badframe;
     84
     85	set_current_blocked(&set);
     86
     87	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
     88		goto badframe;
     89
     90	if (restore_altstack(&frame->uc.uc_stack))
     91		goto badframe;
     92
     93	return regs->gpr[11];
     94
     95badframe:
     96	force_sig(SIGSEGV);
     97	return 0;
     98}
     99
    100/*
    101 * Set up a signal frame.
    102 */
    103
    104static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
    105{
    106	int err = 0;
    107
    108	/* copy the regs */
    109	/* There should be no need to save callee-saved registers here...
    110	 * ...but we save them anyway.  Revisit this
    111	 */
    112	err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long));
    113	err |= __copy_to_user(&sc->regs.pc, &regs->pc, sizeof(unsigned long));
    114	err |= __copy_to_user(&sc->regs.sr, &regs->sr, sizeof(unsigned long));
    115
    116	return err;
    117}
    118
    119static inline unsigned long align_sigframe(unsigned long sp)
    120{
    121	return sp & ~3UL;
    122}
    123
    124/*
    125 * Work out where the signal frame should go.  It's either on the user stack
    126 * or the alternate stack.
    127 */
    128
    129static inline void __user *get_sigframe(struct ksignal *ksig,
    130					struct pt_regs *regs, size_t frame_size)
    131{
    132	unsigned long sp = regs->sp;
    133
    134	/* redzone */
    135	sp -= STACK_FRAME_OVERHEAD;
    136	sp = sigsp(sp, ksig);
    137	sp = align_sigframe(sp - frame_size);
    138
    139	return (void __user *)sp;
    140}
    141
    142/* grab and setup a signal frame.
    143 *
    144 * basically we stack a lot of state info, and arrange for the
    145 * user-mode program to return to the kernel using either a
    146 * trampoline which performs the syscall sigreturn, or a provided
    147 * user-mode trampoline.
    148 */
    149static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
    150			  struct pt_regs *regs)
    151{
    152	struct rt_sigframe __user *frame;
    153	unsigned long return_ip;
    154	int err = 0;
    155
    156	frame = get_sigframe(ksig, regs, sizeof(*frame));
    157
    158	if (!access_ok(frame, sizeof(*frame)))
    159		return -EFAULT;
    160
    161	/* Create siginfo.  */
    162	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
    163		err |= copy_siginfo_to_user(&frame->info, &ksig->info);
    164
    165	/* Create the ucontext.  */
    166	err |= __put_user(0, &frame->uc.uc_flags);
    167	err |= __put_user(NULL, &frame->uc.uc_link);
    168	err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
    169	err |= setup_sigcontext(regs, &frame->uc.uc_mcontext);
    170
    171	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
    172
    173	if (err)
    174		return -EFAULT;
    175
    176	/* trampoline - the desired return ip is the retcode itself */
    177	return_ip = (unsigned long)&frame->retcode;
    178	/* This is:
    179		l.ori r11,r0,__NR_sigreturn
    180		l.sys 1
    181	 */
    182	err |= __put_user(0xa960,             (short __user *)(frame->retcode + 0));
    183	err |= __put_user(__NR_rt_sigreturn,  (short __user *)(frame->retcode + 2));
    184	err |= __put_user(0x20000001, (unsigned long __user *)(frame->retcode + 4));
    185	err |= __put_user(0x15000000, (unsigned long __user *)(frame->retcode + 8));
    186
    187	if (err)
    188		return -EFAULT;
    189
    190	/* Set up registers for signal handler */
    191	regs->pc = (unsigned long)ksig->ka.sa.sa_handler; /* what we enter NOW */
    192	regs->gpr[9] = (unsigned long)return_ip;     /* what we enter LATER */
    193	regs->gpr[3] = (unsigned long)ksig->sig;           /* arg 1: signo */
    194	regs->gpr[4] = (unsigned long)&frame->info;  /* arg 2: (siginfo_t*) */
    195	regs->gpr[5] = (unsigned long)&frame->uc;    /* arg 3: ucontext */
    196
    197	/* actually move the usp to reflect the stacked frame */
    198	regs->sp = (unsigned long)frame;
    199
    200	return 0;
    201}
    202
    203static inline void
    204handle_signal(struct ksignal *ksig, struct pt_regs *regs)
    205{
    206	int ret;
    207
    208	ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
    209
    210	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
    211}
    212
    213/*
    214 * Note that 'init' is a special process: it doesn't get signals it doesn't
    215 * want to handle. Thus you cannot kill init even with a SIGKILL even by
    216 * mistake.
    217 *
    218 * Also note that the regs structure given here as an argument, is the latest
    219 * pushed pt_regs. It may or may not be the same as the first pushed registers
    220 * when the initial usermode->kernelmode transition took place. Therefore
    221 * we can use user_mode(regs) to see if we came directly from kernel or user
    222 * mode below.
    223 */
    224
    225int do_signal(struct pt_regs *regs, int syscall)
    226{
    227	struct ksignal ksig;
    228	unsigned long continue_addr = 0;
    229	unsigned long restart_addr = 0;
    230	unsigned long retval = 0;
    231	int restart = 0;
    232
    233	if (syscall) {
    234		continue_addr = regs->pc;
    235		restart_addr = continue_addr - 4;
    236		retval = regs->gpr[11];
    237
    238		/*
    239		 * Setup syscall restart here so that a debugger will
    240		 * see the already changed PC.
    241		 */
    242		switch (retval) {
    243		case -ERESTART_RESTARTBLOCK:
    244			restart = -2;
    245			fallthrough;
    246		case -ERESTARTNOHAND:
    247		case -ERESTARTSYS:
    248		case -ERESTARTNOINTR:
    249			restart++;
    250			regs->gpr[11] = regs->orig_gpr11;
    251			regs->pc = restart_addr;
    252			break;
    253		}
    254	}
    255
    256	/*
    257	 * Get the signal to deliver.  During the call to get_signal the
    258	 * debugger may change all our registers so we may need to revert
    259	 * the decision to restart the syscall; specifically, if the PC is
    260	 * changed, don't restart the syscall.
    261	 */
    262	if (get_signal(&ksig)) {
    263		if (unlikely(restart) && regs->pc == restart_addr) {
    264			if (retval == -ERESTARTNOHAND ||
    265			    retval == -ERESTART_RESTARTBLOCK
    266			    || (retval == -ERESTARTSYS
    267			        && !(ksig.ka.sa.sa_flags & SA_RESTART))) {
    268				/* No automatic restart */
    269				regs->gpr[11] = -EINTR;
    270				regs->pc = continue_addr;
    271			}
    272		}
    273		handle_signal(&ksig, regs);
    274	} else {
    275		/* no handler */
    276		restore_saved_sigmask();
    277		/*
    278		 * Restore pt_regs PC as syscall restart will be handled by
    279		 * kernel without return to userspace
    280		 */
    281		if (unlikely(restart) && regs->pc == restart_addr) {
    282			regs->pc = continue_addr;
    283			return restart;
    284		}
    285	}
    286
    287	return 0;
    288}
    289
    290asmlinkage int
    291do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
    292{
    293	do {
    294		if (likely(thread_flags & _TIF_NEED_RESCHED)) {
    295			schedule();
    296		} else {
    297			if (unlikely(!user_mode(regs)))
    298				return 0;
    299			local_irq_enable();
    300			if (thread_flags & (_TIF_SIGPENDING|_TIF_NOTIFY_SIGNAL)) {
    301				int restart = do_signal(regs, syscall);
    302				if (unlikely(restart)) {
    303					/*
    304					 * Restart without handlers.
    305					 * Deal with it without leaving
    306					 * the kernel space.
    307					 */
    308					return restart;
    309				}
    310				syscall = 0;
    311			} else {
    312				resume_user_mode_work(regs);
    313			}
    314		}
    315		local_irq_disable();
    316		thread_flags = read_thread_flags();
    317	} while (thread_flags & _TIF_WORK_MASK);
    318	return 0;
    319}