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


      1// SPDX-License-Identifier: GPL-2.0
      2
      3#include <linux/signal.h>
      4#include <linux/uaccess.h>
      5#include <linux/syscalls.h>
      6#include <linux/resume_user_mode.h>
      7
      8#include <asm/traps.h>
      9#include <asm/ucontext.h>
     10#include <asm/vdso.h>
     11
     12#include <abi/regdef.h>
     13
     14#ifdef CONFIG_CPU_HAS_FPU
     15#include <abi/fpu.h>
     16static int restore_fpu_state(struct sigcontext __user *sc)
     17{
     18	int err = 0;
     19	struct user_fp user_fp;
     20
     21	err = __copy_from_user(&user_fp, &sc->sc_user_fp, sizeof(user_fp));
     22
     23	restore_from_user_fp(&user_fp);
     24
     25	return err;
     26}
     27
     28static int save_fpu_state(struct sigcontext __user *sc)
     29{
     30	struct user_fp user_fp;
     31
     32	save_to_user_fp(&user_fp);
     33
     34	return __copy_to_user(&sc->sc_user_fp, &user_fp, sizeof(user_fp));
     35}
     36#else
     37#define restore_fpu_state(sigcontext)	(0)
     38#define save_fpu_state(sigcontext)	(0)
     39#endif
     40
     41struct rt_sigframe {
     42	/*
     43	 * pad[3] is compatible with the same struct defined in
     44	 * gcc/libgcc/config/csky/linux-unwind.h
     45	 */
     46	int pad[3];
     47	struct siginfo info;
     48	struct ucontext uc;
     49};
     50
     51static long restore_sigcontext(struct pt_regs *regs,
     52	struct sigcontext __user *sc)
     53{
     54	int err = 0;
     55	unsigned long sr = regs->sr;
     56
     57	/* sc_pt_regs is structured the same as the start of pt_regs */
     58	err |= __copy_from_user(regs, &sc->sc_pt_regs, sizeof(struct pt_regs));
     59
     60	/* BIT(0) of regs->sr is Condition Code/Carry bit */
     61	regs->sr = (sr & ~1) | (regs->sr & 1);
     62
     63	/* Restore the floating-point state. */
     64	err |= restore_fpu_state(sc);
     65
     66	return err;
     67}
     68
     69SYSCALL_DEFINE0(rt_sigreturn)
     70{
     71	struct pt_regs *regs = current_pt_regs();
     72	struct rt_sigframe __user *frame;
     73	sigset_t set;
     74
     75	/* Always make any pending restarted system calls return -EINTR */
     76	current->restart_block.fn = do_no_restart_syscall;
     77
     78	frame = (struct rt_sigframe __user *)regs->usp;
     79
     80	if (!access_ok(frame, sizeof(*frame)))
     81		goto badframe;
     82
     83	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
     84		goto badframe;
     85
     86	set_current_blocked(&set);
     87
     88	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
     89		goto badframe;
     90
     91	if (restore_altstack(&frame->uc.uc_stack))
     92		goto badframe;
     93
     94	return regs->a0;
     95
     96badframe:
     97	force_sig(SIGSEGV);
     98	return 0;
     99}
    100
    101static int setup_sigcontext(struct rt_sigframe __user *frame,
    102	struct pt_regs *regs)
    103{
    104	struct sigcontext __user *sc = &frame->uc.uc_mcontext;
    105	int err = 0;
    106
    107	err |= __copy_to_user(&sc->sc_pt_regs, regs, sizeof(struct pt_regs));
    108	err |= save_fpu_state(sc);
    109
    110	return err;
    111}
    112
    113static inline void __user *get_sigframe(struct ksignal *ksig,
    114	struct pt_regs *regs, size_t framesize)
    115{
    116	unsigned long sp;
    117	/* Default to using normal stack */
    118	sp = regs->usp;
    119
    120	/*
    121	 * If we are on the alternate signal stack and would overflow it, don't.
    122	 * Return an always-bogus address instead so we will die with SIGSEGV.
    123	 */
    124	if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize)))
    125		return (void __user __force *)(-1UL);
    126
    127	/* This is the X/Open sanctioned signal stack switching. */
    128	sp = sigsp(sp, ksig) - framesize;
    129
    130	/* Align the stack frame. */
    131	sp &= -8UL;
    132
    133	return (void __user *)sp;
    134}
    135
    136static int
    137setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
    138{
    139	struct rt_sigframe __user *frame;
    140	int err = 0;
    141
    142	frame = get_sigframe(ksig, regs, sizeof(*frame));
    143	if (!access_ok(frame, sizeof(*frame)))
    144		return -EFAULT;
    145
    146	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
    147
    148	/* Create the ucontext. */
    149	err |= __put_user(0, &frame->uc.uc_flags);
    150	err |= __put_user(NULL, &frame->uc.uc_link);
    151	err |= __save_altstack(&frame->uc.uc_stack, regs->usp);
    152	err |= setup_sigcontext(frame, regs);
    153	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
    154	if (err)
    155		return -EFAULT;
    156
    157	/* Set up to return from userspace. */
    158	regs->lr = (unsigned long)VDSO_SYMBOL(
    159		current->mm->context.vdso, rt_sigreturn);
    160
    161	/*
    162	 * Set up registers for signal handler.
    163	 * Registers that we don't modify keep the value they had from
    164	 * user-space at the time we took the signal.
    165	 * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
    166	 * since some things rely on this (e.g. glibc's debug/segfault.c).
    167	 */
    168	regs->pc  = (unsigned long)ksig->ka.sa.sa_handler;
    169	regs->usp = (unsigned long)frame;
    170	regs->a0  = ksig->sig;				/* a0: signal number */
    171	regs->a1  = (unsigned long)(&(frame->info));	/* a1: siginfo pointer */
    172	regs->a2  = (unsigned long)(&(frame->uc));	/* a2: ucontext pointer */
    173
    174	return 0;
    175}
    176
    177static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
    178{
    179	sigset_t *oldset = sigmask_to_save();
    180	int ret;
    181
    182	rseq_signal_deliver(ksig, regs);
    183
    184	/* Are we from a system call? */
    185	if (in_syscall(regs)) {
    186		/* Avoid additional syscall restarting via ret_from_exception */
    187		forget_syscall(regs);
    188
    189		/* If so, check system call restarting.. */
    190		switch (regs->a0) {
    191		case -ERESTART_RESTARTBLOCK:
    192		case -ERESTARTNOHAND:
    193			regs->a0 = -EINTR;
    194			break;
    195
    196		case -ERESTARTSYS:
    197			if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
    198				regs->a0 = -EINTR;
    199				break;
    200			}
    201			fallthrough;
    202		case -ERESTARTNOINTR:
    203			regs->a0 = regs->orig_a0;
    204			regs->pc -= TRAP0_SIZE;
    205			break;
    206		}
    207	}
    208
    209	/* Set up the stack frame */
    210	ret = setup_rt_frame(ksig, oldset, regs);
    211
    212	signal_setup_done(ret, ksig, 0);
    213}
    214
    215static void do_signal(struct pt_regs *regs)
    216{
    217	struct ksignal ksig;
    218
    219	if (get_signal(&ksig)) {
    220		/* Actually deliver the signal */
    221		handle_signal(&ksig, regs);
    222		return;
    223	}
    224
    225	/* Did we come from a system call? */
    226	if (in_syscall(regs)) {
    227		/* Avoid additional syscall restarting via ret_from_exception */
    228		forget_syscall(regs);
    229
    230		/* Restart the system call - no handlers present */
    231		switch (regs->a0) {
    232		case -ERESTARTNOHAND:
    233		case -ERESTARTSYS:
    234		case -ERESTARTNOINTR:
    235			regs->a0 = regs->orig_a0;
    236			regs->pc -= TRAP0_SIZE;
    237			break;
    238		case -ERESTART_RESTARTBLOCK:
    239			regs->a0 = regs->orig_a0;
    240			regs_syscallid(regs) = __NR_restart_syscall;
    241			regs->pc -= TRAP0_SIZE;
    242			break;
    243		}
    244	}
    245
    246	/*
    247	 * If there is no signal to deliver, we just put the saved
    248	 * sigmask back.
    249	 */
    250	restore_saved_sigmask();
    251}
    252
    253/*
    254 * notification of userspace execution resumption
    255 * - triggered by the _TIF_WORK_MASK flags
    256 */
    257asmlinkage void do_notify_resume(struct pt_regs *regs,
    258	unsigned long thread_info_flags)
    259{
    260	if (thread_info_flags & _TIF_UPROBE)
    261		uprobe_notify_resume(regs);
    262
    263	/* Handle pending signal delivery */
    264	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
    265		do_signal(regs);
    266
    267	if (thread_info_flags & _TIF_NOTIFY_RESUME)
    268		resume_user_mode_work(regs);
    269}