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


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Signal support for Hexagon processor
      4 *
      5 * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
      6 */
      7
      8#include <linux/linkage.h>
      9#include <linux/syscalls.h>
     10#include <linux/sched/task_stack.h>
     11
     12#include <asm/registers.h>
     13#include <asm/thread_info.h>
     14#include <asm/unistd.h>
     15#include <linux/uaccess.h>
     16#include <asm/ucontext.h>
     17#include <asm/cacheflush.h>
     18#include <asm/signal.h>
     19#include <asm/vdso.h>
     20
     21struct rt_sigframe {
     22	unsigned long tramp[2];
     23	struct siginfo info;
     24	struct ucontext uc;
     25};
     26
     27static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
     28			  size_t frame_size)
     29{
     30	unsigned long sp = sigsp(regs->r29, ksig);
     31
     32	return (void __user *)((sp - frame_size) & ~(sizeof(long long) - 1));
     33}
     34
     35static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
     36{
     37	unsigned long tmp;
     38	int err = 0;
     39
     40	err |= copy_to_user(&sc->sc_regs.r0, &regs->r00,
     41			    32*sizeof(unsigned long));
     42
     43	err |= __put_user(regs->sa0, &sc->sc_regs.sa0);
     44	err |= __put_user(regs->lc0, &sc->sc_regs.lc0);
     45	err |= __put_user(regs->sa1, &sc->sc_regs.sa1);
     46	err |= __put_user(regs->lc1, &sc->sc_regs.lc1);
     47	err |= __put_user(regs->m0, &sc->sc_regs.m0);
     48	err |= __put_user(regs->m1, &sc->sc_regs.m1);
     49	err |= __put_user(regs->usr, &sc->sc_regs.usr);
     50	err |= __put_user(regs->preds, &sc->sc_regs.p3_0);
     51	err |= __put_user(regs->gp, &sc->sc_regs.gp);
     52	err |= __put_user(regs->ugp, &sc->sc_regs.ugp);
     53#if CONFIG_HEXAGON_ARCH_VERSION >= 4
     54	err |= __put_user(regs->cs0, &sc->sc_regs.cs0);
     55	err |= __put_user(regs->cs1, &sc->sc_regs.cs1);
     56#endif
     57	tmp = pt_elr(regs); err |= __put_user(tmp, &sc->sc_regs.pc);
     58	tmp = pt_cause(regs); err |= __put_user(tmp, &sc->sc_regs.cause);
     59	tmp = pt_badva(regs); err |= __put_user(tmp, &sc->sc_regs.badva);
     60
     61	return err;
     62}
     63
     64static int restore_sigcontext(struct pt_regs *regs,
     65			      struct sigcontext __user *sc)
     66{
     67	unsigned long tmp;
     68	int err = 0;
     69
     70	err |= copy_from_user(&regs->r00, &sc->sc_regs.r0,
     71			      32 * sizeof(unsigned long));
     72
     73	err |= __get_user(regs->sa0, &sc->sc_regs.sa0);
     74	err |= __get_user(regs->lc0, &sc->sc_regs.lc0);
     75	err |= __get_user(regs->sa1, &sc->sc_regs.sa1);
     76	err |= __get_user(regs->lc1, &sc->sc_regs.lc1);
     77	err |= __get_user(regs->m0, &sc->sc_regs.m0);
     78	err |= __get_user(regs->m1, &sc->sc_regs.m1);
     79	err |= __get_user(regs->usr, &sc->sc_regs.usr);
     80	err |= __get_user(regs->preds, &sc->sc_regs.p3_0);
     81	err |= __get_user(regs->gp, &sc->sc_regs.gp);
     82	err |= __get_user(regs->ugp, &sc->sc_regs.ugp);
     83#if CONFIG_HEXAGON_ARCH_VERSION >= 4
     84	err |= __get_user(regs->cs0, &sc->sc_regs.cs0);
     85	err |= __get_user(regs->cs1, &sc->sc_regs.cs1);
     86#endif
     87	err |= __get_user(tmp, &sc->sc_regs.pc); pt_set_elr(regs, tmp);
     88
     89	return err;
     90}
     91
     92/*
     93 * Setup signal stack frame with siginfo structure
     94 */
     95static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
     96			  struct pt_regs *regs)
     97{
     98	int err = 0;
     99	struct rt_sigframe __user *frame;
    100	struct hexagon_vdso *vdso = current->mm->context.vdso;
    101
    102	frame = get_sigframe(ksig, regs, sizeof(struct rt_sigframe));
    103
    104	if (!access_ok(frame, sizeof(struct rt_sigframe)))
    105		return -EFAULT;
    106
    107	if (copy_siginfo_to_user(&frame->info, &ksig->info))
    108		return -EFAULT;
    109
    110	/* The on-stack signal trampoline is no longer executed;
    111	 * however, the libgcc signal frame unwinding code checks for
    112	 * the presence of these two numeric magic values.
    113	 */
    114	err |= __put_user(0x7800d166, &frame->tramp[0]);
    115	err |= __put_user(0x5400c004, &frame->tramp[1]);
    116	err |= setup_sigcontext(regs, &frame->uc.uc_mcontext);
    117	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
    118	err |= __save_altstack(&frame->uc.uc_stack, user_stack_pointer(regs));
    119	if (err)
    120		return -EFAULT;
    121
    122	/* Load r0/r1 pair with signumber/siginfo pointer... */
    123	regs->r0100 = ((unsigned long long)((unsigned long)&frame->info) << 32)
    124		| (unsigned long long)ksig->sig;
    125	regs->r02 = (unsigned long) &frame->uc;
    126	regs->r31 = (unsigned long) vdso->rt_signal_trampoline;
    127	pt_psp(regs) = (unsigned long) frame;
    128	pt_set_elr(regs, (unsigned long)ksig->ka.sa.sa_handler);
    129
    130	return 0;
    131}
    132
    133/*
    134 * Setup invocation of signal handler
    135 */
    136static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
    137{
    138	int ret;
    139
    140	/*
    141	 * If we're handling a signal that aborted a system call,
    142	 * set up the error return value before adding the signal
    143	 * frame to the stack.
    144	 */
    145
    146	if (regs->syscall_nr >= 0) {
    147		switch (regs->r00) {
    148		case -ERESTART_RESTARTBLOCK:
    149		case -ERESTARTNOHAND:
    150			regs->r00 = -EINTR;
    151			break;
    152		case -ERESTARTSYS:
    153			if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
    154				regs->r00 = -EINTR;
    155				break;
    156			}
    157			fallthrough;
    158		case -ERESTARTNOINTR:
    159			regs->r06 = regs->syscall_nr;
    160			pt_set_elr(regs, pt_elr(regs) - 4);
    161			regs->r00 = regs->restart_r0;
    162			break;
    163		default:
    164			break;
    165		}
    166	}
    167
    168	/*
    169	 * Set up the stack frame; not doing the SA_SIGINFO thing.  We
    170	 * only set up the rt_frame flavor.
    171	 */
    172	/* If there was an error on setup, no signal was delivered. */
    173	ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
    174
    175	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
    176}
    177
    178/*
    179 * Called from return-from-event code.
    180 */
    181void do_signal(struct pt_regs *regs)
    182{
    183	struct ksignal ksig;
    184
    185	if (!user_mode(regs))
    186		return;
    187
    188	if (get_signal(&ksig)) {
    189		handle_signal(&ksig, regs);
    190		return;
    191	}
    192
    193	/*
    194	 * No (more) signals; if we came from a system call, handle the restart.
    195	 */
    196
    197	if (regs->syscall_nr >= 0) {
    198		switch (regs->r00) {
    199		case -ERESTARTNOHAND:
    200		case -ERESTARTSYS:
    201		case -ERESTARTNOINTR:
    202			regs->r06 = regs->syscall_nr;
    203			break;
    204		case -ERESTART_RESTARTBLOCK:
    205			regs->r06 = __NR_restart_syscall;
    206			break;
    207		default:
    208			goto no_restart;
    209		}
    210		pt_set_elr(regs, pt_elr(regs) - 4);
    211		regs->r00 = regs->restart_r0;
    212	}
    213
    214no_restart:
    215	/* If there's no signal to deliver, put the saved sigmask back */
    216	restore_saved_sigmask();
    217}
    218
    219/*
    220 * Architecture-specific wrappers for signal-related system calls
    221 */
    222
    223asmlinkage int sys_rt_sigreturn(void)
    224{
    225	struct pt_regs *regs = current_pt_regs();
    226	struct rt_sigframe __user *frame;
    227	sigset_t blocked;
    228
    229	/* Always make any pending restarted system calls return -EINTR */
    230	current->restart_block.fn = do_no_restart_syscall;
    231
    232	frame = (struct rt_sigframe __user *)pt_psp(regs);
    233	if (!access_ok(frame, sizeof(*frame)))
    234		goto badframe;
    235	if (__copy_from_user(&blocked, &frame->uc.uc_sigmask, sizeof(blocked)))
    236		goto badframe;
    237
    238	set_current_blocked(&blocked);
    239
    240	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
    241		goto badframe;
    242
    243	/* Restore the user's stack as well */
    244	pt_psp(regs) = regs->r29;
    245
    246	regs->syscall_nr = -1;
    247
    248	if (restore_altstack(&frame->uc.uc_stack))
    249		goto badframe;
    250
    251	return regs->r00;
    252
    253badframe:
    254	force_sig(SIGSEGV);
    255	return 0;
    256}