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


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
      4 *  Chen Liqin <liqin.chen@sunplusct.com>
      5 *  Lennox Wu <lennox.wu@sunplusct.com>
      6 * Copyright (C) 2012 Regents of the University of California
      7 */
      8
      9#include <linux/compat.h>
     10#include <linux/signal.h>
     11#include <linux/uaccess.h>
     12#include <linux/syscalls.h>
     13#include <linux/resume_user_mode.h>
     14#include <linux/linkage.h>
     15
     16#include <asm/ucontext.h>
     17#include <asm/vdso.h>
     18#include <asm/signal32.h>
     19#include <asm/switch_to.h>
     20#include <asm/csr.h>
     21
     22extern u32 __user_rt_sigreturn[2];
     23
     24#define DEBUG_SIG 0
     25
     26struct rt_sigframe {
     27	struct siginfo info;
     28	struct ucontext uc;
     29#ifndef CONFIG_MMU
     30	u32 sigreturn_code[2];
     31#endif
     32};
     33
     34#ifdef CONFIG_FPU
     35static long restore_fp_state(struct pt_regs *regs,
     36			     union __riscv_fp_state __user *sc_fpregs)
     37{
     38	long err;
     39	struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
     40	size_t i;
     41
     42	err = __copy_from_user(&current->thread.fstate, state, sizeof(*state));
     43	if (unlikely(err))
     44		return err;
     45
     46	fstate_restore(current, regs);
     47
     48	/* We support no other extension state at this time. */
     49	for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
     50		u32 value;
     51
     52		err = __get_user(value, &sc_fpregs->q.reserved[i]);
     53		if (unlikely(err))
     54			break;
     55		if (value != 0)
     56			return -EINVAL;
     57	}
     58
     59	return err;
     60}
     61
     62static long save_fp_state(struct pt_regs *regs,
     63			  union __riscv_fp_state __user *sc_fpregs)
     64{
     65	long err;
     66	struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
     67	size_t i;
     68
     69	fstate_save(current, regs);
     70	err = __copy_to_user(state, &current->thread.fstate, sizeof(*state));
     71	if (unlikely(err))
     72		return err;
     73
     74	/* We support no other extension state at this time. */
     75	for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
     76		err = __put_user(0, &sc_fpregs->q.reserved[i]);
     77		if (unlikely(err))
     78			break;
     79	}
     80
     81	return err;
     82}
     83#else
     84#define save_fp_state(task, regs) (0)
     85#define restore_fp_state(task, regs) (0)
     86#endif
     87
     88static long restore_sigcontext(struct pt_regs *regs,
     89	struct sigcontext __user *sc)
     90{
     91	long err;
     92	/* sc_regs is structured the same as the start of pt_regs */
     93	err = __copy_from_user(regs, &sc->sc_regs, sizeof(sc->sc_regs));
     94	/* Restore the floating-point state. */
     95	if (has_fpu())
     96		err |= restore_fp_state(regs, &sc->sc_fpregs);
     97	return err;
     98}
     99
    100SYSCALL_DEFINE0(rt_sigreturn)
    101{
    102	struct pt_regs *regs = current_pt_regs();
    103	struct rt_sigframe __user *frame;
    104	struct task_struct *task;
    105	sigset_t set;
    106
    107	/* Always make any pending restarted system calls return -EINTR */
    108	current->restart_block.fn = do_no_restart_syscall;
    109
    110	frame = (struct rt_sigframe __user *)regs->sp;
    111
    112	if (!access_ok(frame, sizeof(*frame)))
    113		goto badframe;
    114
    115	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
    116		goto badframe;
    117
    118	set_current_blocked(&set);
    119
    120	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
    121		goto badframe;
    122
    123	if (restore_altstack(&frame->uc.uc_stack))
    124		goto badframe;
    125
    126	return regs->a0;
    127
    128badframe:
    129	task = current;
    130	if (show_unhandled_signals) {
    131		pr_info_ratelimited(
    132			"%s[%d]: bad frame in %s: frame=%p pc=%p sp=%p\n",
    133			task->comm, task_pid_nr(task), __func__,
    134			frame, (void *)regs->epc, (void *)regs->sp);
    135	}
    136	force_sig(SIGSEGV);
    137	return 0;
    138}
    139
    140static long setup_sigcontext(struct rt_sigframe __user *frame,
    141	struct pt_regs *regs)
    142{
    143	struct sigcontext __user *sc = &frame->uc.uc_mcontext;
    144	long err;
    145	/* sc_regs is structured the same as the start of pt_regs */
    146	err = __copy_to_user(&sc->sc_regs, regs, sizeof(sc->sc_regs));
    147	/* Save the floating-point state. */
    148	if (has_fpu())
    149		err |= save_fp_state(regs, &sc->sc_fpregs);
    150	return err;
    151}
    152
    153static inline void __user *get_sigframe(struct ksignal *ksig,
    154	struct pt_regs *regs, size_t framesize)
    155{
    156	unsigned long sp;
    157	/* Default to using normal stack */
    158	sp = regs->sp;
    159
    160	/*
    161	 * If we are on the alternate signal stack and would overflow it, don't.
    162	 * Return an always-bogus address instead so we will die with SIGSEGV.
    163	 */
    164	if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize)))
    165		return (void __user __force *)(-1UL);
    166
    167	/* This is the X/Open sanctioned signal stack switching. */
    168	sp = sigsp(sp, ksig) - framesize;
    169
    170	/* Align the stack frame. */
    171	sp &= ~0xfUL;
    172
    173	return (void __user *)sp;
    174}
    175
    176static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
    177	struct pt_regs *regs)
    178{
    179	struct rt_sigframe __user *frame;
    180	long err = 0;
    181
    182	frame = get_sigframe(ksig, regs, sizeof(*frame));
    183	if (!access_ok(frame, sizeof(*frame)))
    184		return -EFAULT;
    185
    186	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
    187
    188	/* Create the ucontext. */
    189	err |= __put_user(0, &frame->uc.uc_flags);
    190	err |= __put_user(NULL, &frame->uc.uc_link);
    191	err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
    192	err |= setup_sigcontext(frame, regs);
    193	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
    194	if (err)
    195		return -EFAULT;
    196
    197	/* Set up to return from userspace. */
    198#ifdef CONFIG_MMU
    199	regs->ra = (unsigned long)VDSO_SYMBOL(
    200		current->mm->context.vdso, rt_sigreturn);
    201#else
    202	/*
    203	 * For the nommu case we don't have a VDSO.  Instead we push two
    204	 * instructions to call the rt_sigreturn syscall onto the user stack.
    205	 */
    206	if (copy_to_user(&frame->sigreturn_code, __user_rt_sigreturn,
    207			 sizeof(frame->sigreturn_code)))
    208		return -EFAULT;
    209	regs->ra = (unsigned long)&frame->sigreturn_code;
    210#endif /* CONFIG_MMU */
    211
    212	/*
    213	 * Set up registers for signal handler.
    214	 * Registers that we don't modify keep the value they had from
    215	 * user-space at the time we took the signal.
    216	 * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
    217	 * since some things rely on this (e.g. glibc's debug/segfault.c).
    218	 */
    219	regs->epc = (unsigned long)ksig->ka.sa.sa_handler;
    220	regs->sp = (unsigned long)frame;
    221	regs->a0 = ksig->sig;                     /* a0: signal number */
    222	regs->a1 = (unsigned long)(&frame->info); /* a1: siginfo pointer */
    223	regs->a2 = (unsigned long)(&frame->uc);   /* a2: ucontext pointer */
    224
    225#if DEBUG_SIG
    226	pr_info("SIG deliver (%s:%d): sig=%d pc=%p ra=%p sp=%p\n",
    227		current->comm, task_pid_nr(current), ksig->sig,
    228		(void *)regs->epc, (void *)regs->ra, frame);
    229#endif
    230
    231	return 0;
    232}
    233
    234static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
    235{
    236	sigset_t *oldset = sigmask_to_save();
    237	int ret;
    238
    239	/* Are we from a system call? */
    240	if (regs->cause == EXC_SYSCALL) {
    241		/* Avoid additional syscall restarting via ret_from_exception */
    242		regs->cause = -1UL;
    243		/* If so, check system call restarting.. */
    244		switch (regs->a0) {
    245		case -ERESTART_RESTARTBLOCK:
    246		case -ERESTARTNOHAND:
    247			regs->a0 = -EINTR;
    248			break;
    249
    250		case -ERESTARTSYS:
    251			if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
    252				regs->a0 = -EINTR;
    253				break;
    254			}
    255			fallthrough;
    256		case -ERESTARTNOINTR:
    257                        regs->a0 = regs->orig_a0;
    258			regs->epc -= 0x4;
    259			break;
    260		}
    261	}
    262
    263	rseq_signal_deliver(ksig, regs);
    264
    265	/* Set up the stack frame */
    266	if (is_compat_task())
    267		ret = compat_setup_rt_frame(ksig, oldset, regs);
    268	else
    269		ret = setup_rt_frame(ksig, oldset, regs);
    270
    271	signal_setup_done(ret, ksig, 0);
    272}
    273
    274static void do_signal(struct pt_regs *regs)
    275{
    276	struct ksignal ksig;
    277
    278	if (get_signal(&ksig)) {
    279		/* Actually deliver the signal */
    280		handle_signal(&ksig, regs);
    281		return;
    282	}
    283
    284	/* Did we come from a system call? */
    285	if (regs->cause == EXC_SYSCALL) {
    286		/* Avoid additional syscall restarting via ret_from_exception */
    287		regs->cause = -1UL;
    288
    289		/* Restart the system call - no handlers present */
    290		switch (regs->a0) {
    291		case -ERESTARTNOHAND:
    292		case -ERESTARTSYS:
    293		case -ERESTARTNOINTR:
    294                        regs->a0 = regs->orig_a0;
    295			regs->epc -= 0x4;
    296			break;
    297		case -ERESTART_RESTARTBLOCK:
    298                        regs->a0 = regs->orig_a0;
    299			regs->a7 = __NR_restart_syscall;
    300			regs->epc -= 0x4;
    301			break;
    302		}
    303	}
    304
    305	/*
    306	 * If there is no signal to deliver, we just put the saved
    307	 * sigmask back.
    308	 */
    309	restore_saved_sigmask();
    310}
    311
    312/*
    313 * notification of userspace execution resumption
    314 * - triggered by the _TIF_WORK_MASK flags
    315 */
    316asmlinkage __visible void do_notify_resume(struct pt_regs *regs,
    317					   unsigned long thread_info_flags)
    318{
    319	if (thread_info_flags & _TIF_UPROBE)
    320		uprobe_notify_resume(regs);
    321
    322	/* Handle pending signal delivery */
    323	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
    324		do_signal(regs);
    325
    326	if (thread_info_flags & _TIF_NOTIFY_RESUME)
    327		resume_user_mode_work(regs);
    328}