1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * linux/arch/alpha/kernel/signal.c 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Copyright (C) 1995 Linus Torvalds 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * 1997-11-02 Modified for POSIX.1b signals by Richard Henderson 81da177e4SLinus Torvalds */ 91da177e4SLinus Torvalds 103f07c014SIngo Molnar #include <linux/sched/signal.h> 1168db0cf1SIngo Molnar #include <linux/sched/task_stack.h> 121da177e4SLinus Torvalds #include <linux/kernel.h> 131da177e4SLinus Torvalds #include <linux/signal.h> 141da177e4SLinus Torvalds #include <linux/errno.h> 151da177e4SLinus Torvalds #include <linux/wait.h> 161da177e4SLinus Torvalds #include <linux/ptrace.h> 171da177e4SLinus Torvalds #include <linux/unistd.h> 181da177e4SLinus Torvalds #include <linux/mm.h> 191da177e4SLinus Torvalds #include <linux/smp.h> 201da177e4SLinus Torvalds #include <linux/stddef.h> 211da177e4SLinus Torvalds #include <linux/tty.h> 221da177e4SLinus Torvalds #include <linux/binfmts.h> 231da177e4SLinus Torvalds #include <linux/bitops.h> 24e5d9a90cSIvan Kokshaysky #include <linux/syscalls.h> 25733e5e4bSDavid Howells #include <linux/tracehook.h> 261da177e4SLinus Torvalds 277c0f6ba6SLinus Torvalds #include <linux/uaccess.h> 281da177e4SLinus Torvalds #include <asm/sigcontext.h> 291da177e4SLinus Torvalds #include <asm/ucontext.h> 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds #include "proto.h" 321da177e4SLinus Torvalds 331da177e4SLinus Torvalds 341da177e4SLinus Torvalds #define DEBUG_SIG 0 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 371da177e4SLinus Torvalds 381da177e4SLinus Torvalds asmlinkage void ret_from_sys_call(void); 391da177e4SLinus Torvalds 401da177e4SLinus Torvalds /* 411da177e4SLinus Torvalds * The OSF/1 sigprocmask calling sequence is different from the 421da177e4SLinus Torvalds * C sigprocmask() sequence.. 431da177e4SLinus Torvalds */ 44c52c2ddcSAl Viro SYSCALL_DEFINE2(osf_sigprocmask, int, how, unsigned long, newmask) 451da177e4SLinus Torvalds { 46c52c2ddcSAl Viro sigset_t oldmask; 47c52c2ddcSAl Viro sigset_t mask; 48c52c2ddcSAl Viro unsigned long res; 491da177e4SLinus Torvalds 5087400e54SLinus Torvalds siginitset(&mask, newmask & _BLOCKABLE); 510f44fbd2SLinus Torvalds res = sigprocmask(how, &mask, &oldmask); 52c52c2ddcSAl Viro if (!res) { 53c52c2ddcSAl Viro force_successful_syscall_return(); 540f44fbd2SLinus Torvalds res = oldmask.sig[0]; 551da177e4SLinus Torvalds } 56c52c2ddcSAl Viro return res; 571da177e4SLinus Torvalds } 581da177e4SLinus Torvalds 59e5d9a90cSIvan Kokshaysky SYSCALL_DEFINE3(osf_sigaction, int, sig, 60e5d9a90cSIvan Kokshaysky const struct osf_sigaction __user *, act, 61e5d9a90cSIvan Kokshaysky struct osf_sigaction __user *, oact) 621da177e4SLinus Torvalds { 631da177e4SLinus Torvalds struct k_sigaction new_ka, old_ka; 641da177e4SLinus Torvalds int ret; 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds if (act) { 671da177e4SLinus Torvalds old_sigset_t mask; 6896d4f267SLinus Torvalds if (!access_ok(act, sizeof(*act)) || 691da177e4SLinus Torvalds __get_user(new_ka.sa.sa_handler, &act->sa_handler) || 7018e6bfa9SAl Viro __get_user(new_ka.sa.sa_flags, &act->sa_flags) || 7118e6bfa9SAl Viro __get_user(mask, &act->sa_mask)) 721da177e4SLinus Torvalds return -EFAULT; 731da177e4SLinus Torvalds siginitset(&new_ka.sa.sa_mask, mask); 741da177e4SLinus Torvalds new_ka.ka_restorer = NULL; 751da177e4SLinus Torvalds } 761da177e4SLinus Torvalds 771da177e4SLinus Torvalds ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds if (!ret && oact) { 8096d4f267SLinus Torvalds if (!access_ok(oact, sizeof(*oact)) || 811da177e4SLinus Torvalds __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || 8218e6bfa9SAl Viro __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || 8318e6bfa9SAl Viro __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) 841da177e4SLinus Torvalds return -EFAULT; 851da177e4SLinus Torvalds } 861da177e4SLinus Torvalds 871da177e4SLinus Torvalds return ret; 881da177e4SLinus Torvalds } 891da177e4SLinus Torvalds 90e5d9a90cSIvan Kokshaysky SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act, 91e5d9a90cSIvan Kokshaysky struct sigaction __user *, oact, 92e5d9a90cSIvan Kokshaysky size_t, sigsetsize, void __user *, restorer) 931da177e4SLinus Torvalds { 941da177e4SLinus Torvalds struct k_sigaction new_ka, old_ka; 951da177e4SLinus Torvalds int ret; 961da177e4SLinus Torvalds 971da177e4SLinus Torvalds /* XXX: Don't preclude handling different sized sigset_t's. */ 981da177e4SLinus Torvalds if (sigsetsize != sizeof(sigset_t)) 991da177e4SLinus Torvalds return -EINVAL; 1001da177e4SLinus Torvalds 1011da177e4SLinus Torvalds if (act) { 1021da177e4SLinus Torvalds new_ka.ka_restorer = restorer; 1031da177e4SLinus Torvalds if (copy_from_user(&new_ka.sa, act, sizeof(*act))) 1041da177e4SLinus Torvalds return -EFAULT; 1051da177e4SLinus Torvalds } 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds if (!ret && oact) { 1101da177e4SLinus Torvalds if (copy_to_user(oact, &old_ka.sa, sizeof(*oact))) 1111da177e4SLinus Torvalds return -EFAULT; 1121da177e4SLinus Torvalds } 1131da177e4SLinus Torvalds 1141da177e4SLinus Torvalds return ret; 1151da177e4SLinus Torvalds } 1161da177e4SLinus Torvalds 1171da177e4SLinus Torvalds /* 1181da177e4SLinus Torvalds * Do a signal return; undo the signal stack. 1191da177e4SLinus Torvalds */ 1201da177e4SLinus Torvalds 1211da177e4SLinus Torvalds #if _NSIG_WORDS > 1 1221da177e4SLinus Torvalds # error "Non SA_SIGINFO frame needs rearranging" 1231da177e4SLinus Torvalds #endif 1241da177e4SLinus Torvalds 1251da177e4SLinus Torvalds struct sigframe 1261da177e4SLinus Torvalds { 1271da177e4SLinus Torvalds struct sigcontext sc; 1281da177e4SLinus Torvalds unsigned int retcode[3]; 1291da177e4SLinus Torvalds }; 1301da177e4SLinus Torvalds 1311da177e4SLinus Torvalds struct rt_sigframe 1321da177e4SLinus Torvalds { 1331da177e4SLinus Torvalds struct siginfo info; 1341da177e4SLinus Torvalds struct ucontext uc; 1351da177e4SLinus Torvalds unsigned int retcode[3]; 1361da177e4SLinus Torvalds }; 1371da177e4SLinus Torvalds 1381da177e4SLinus Torvalds /* If this changes, userland unwinders that Know Things about our signal 1391da177e4SLinus Torvalds frame will break. Do not undertake lightly. It also implies an ABI 1401da177e4SLinus Torvalds change wrt the size of siginfo_t, which may cause some pain. */ 1411da177e4SLinus Torvalds extern char compile_time_assert 1421da177e4SLinus Torvalds [offsetof(struct rt_sigframe, uc.uc_mcontext) == 176 ? 1 : -1]; 1431da177e4SLinus Torvalds 1441da177e4SLinus Torvalds #define INSN_MOV_R30_R16 0x47fe0410 1451da177e4SLinus Torvalds #define INSN_LDI_R0 0x201f0000 1461da177e4SLinus Torvalds #define INSN_CALLSYS 0x00000083 1471da177e4SLinus Torvalds 1481da177e4SLinus Torvalds static long 149b960f303SAl Viro restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) 1501da177e4SLinus Torvalds { 1511da177e4SLinus Torvalds unsigned long usp; 152b960f303SAl Viro struct switch_stack *sw = (struct switch_stack *)regs - 1; 1531da177e4SLinus Torvalds long i, err = __get_user(regs->pc, &sc->sc_pc); 1541da177e4SLinus Torvalds 155f56141e3SAndy Lutomirski current->restart_block.fn = do_no_restart_syscall; 1562deba1bdSAl Viro 1571da177e4SLinus Torvalds sw->r26 = (unsigned long) ret_from_sys_call; 1581da177e4SLinus Torvalds 1591da177e4SLinus Torvalds err |= __get_user(regs->r0, sc->sc_regs+0); 1601da177e4SLinus Torvalds err |= __get_user(regs->r1, sc->sc_regs+1); 1611da177e4SLinus Torvalds err |= __get_user(regs->r2, sc->sc_regs+2); 1621da177e4SLinus Torvalds err |= __get_user(regs->r3, sc->sc_regs+3); 1631da177e4SLinus Torvalds err |= __get_user(regs->r4, sc->sc_regs+4); 1641da177e4SLinus Torvalds err |= __get_user(regs->r5, sc->sc_regs+5); 1651da177e4SLinus Torvalds err |= __get_user(regs->r6, sc->sc_regs+6); 1661da177e4SLinus Torvalds err |= __get_user(regs->r7, sc->sc_regs+7); 1671da177e4SLinus Torvalds err |= __get_user(regs->r8, sc->sc_regs+8); 1681da177e4SLinus Torvalds err |= __get_user(sw->r9, sc->sc_regs+9); 1691da177e4SLinus Torvalds err |= __get_user(sw->r10, sc->sc_regs+10); 1701da177e4SLinus Torvalds err |= __get_user(sw->r11, sc->sc_regs+11); 1711da177e4SLinus Torvalds err |= __get_user(sw->r12, sc->sc_regs+12); 1721da177e4SLinus Torvalds err |= __get_user(sw->r13, sc->sc_regs+13); 1731da177e4SLinus Torvalds err |= __get_user(sw->r14, sc->sc_regs+14); 1741da177e4SLinus Torvalds err |= __get_user(sw->r15, sc->sc_regs+15); 1751da177e4SLinus Torvalds err |= __get_user(regs->r16, sc->sc_regs+16); 1761da177e4SLinus Torvalds err |= __get_user(regs->r17, sc->sc_regs+17); 1771da177e4SLinus Torvalds err |= __get_user(regs->r18, sc->sc_regs+18); 1781da177e4SLinus Torvalds err |= __get_user(regs->r19, sc->sc_regs+19); 1791da177e4SLinus Torvalds err |= __get_user(regs->r20, sc->sc_regs+20); 1801da177e4SLinus Torvalds err |= __get_user(regs->r21, sc->sc_regs+21); 1811da177e4SLinus Torvalds err |= __get_user(regs->r22, sc->sc_regs+22); 1821da177e4SLinus Torvalds err |= __get_user(regs->r23, sc->sc_regs+23); 1831da177e4SLinus Torvalds err |= __get_user(regs->r24, sc->sc_regs+24); 1841da177e4SLinus Torvalds err |= __get_user(regs->r25, sc->sc_regs+25); 1851da177e4SLinus Torvalds err |= __get_user(regs->r26, sc->sc_regs+26); 1861da177e4SLinus Torvalds err |= __get_user(regs->r27, sc->sc_regs+27); 1871da177e4SLinus Torvalds err |= __get_user(regs->r28, sc->sc_regs+28); 1881da177e4SLinus Torvalds err |= __get_user(regs->gp, sc->sc_regs+29); 1891da177e4SLinus Torvalds err |= __get_user(usp, sc->sc_regs+30); 1901da177e4SLinus Torvalds wrusp(usp); 1911da177e4SLinus Torvalds 1921da177e4SLinus Torvalds for (i = 0; i < 31; i++) 1931da177e4SLinus Torvalds err |= __get_user(sw->fp[i], sc->sc_fpregs+i); 1941da177e4SLinus Torvalds err |= __get_user(sw->fp[31], &sc->sc_fpcr); 1951da177e4SLinus Torvalds 1961da177e4SLinus Torvalds return err; 1971da177e4SLinus Torvalds } 1981da177e4SLinus Torvalds 1991da177e4SLinus Torvalds /* Note that this syscall is also used by setcontext(3) to install 2001da177e4SLinus Torvalds a given sigcontext. This because it's impossible to set *all* 2011da177e4SLinus Torvalds registers and transfer control from userland. */ 2021da177e4SLinus Torvalds 2031da177e4SLinus Torvalds asmlinkage void 204b960f303SAl Viro do_sigreturn(struct sigcontext __user *sc) 2051da177e4SLinus Torvalds { 206b960f303SAl Viro struct pt_regs *regs = current_pt_regs(); 2071da177e4SLinus Torvalds sigset_t set; 2081da177e4SLinus Torvalds 2091da177e4SLinus Torvalds /* Verify that it's a good sigcontext before using it */ 21096d4f267SLinus Torvalds if (!access_ok(sc, sizeof(*sc))) 2111da177e4SLinus Torvalds goto give_sigsegv; 2121da177e4SLinus Torvalds if (__get_user(set.sig[0], &sc->sc_mask)) 2131da177e4SLinus Torvalds goto give_sigsegv; 2141da177e4SLinus Torvalds 2152561b069SMatt Fleming set_current_blocked(&set); 2161da177e4SLinus Torvalds 217b960f303SAl Viro if (restore_sigcontext(sc, regs)) 2181da177e4SLinus Torvalds goto give_sigsegv; 2191da177e4SLinus Torvalds 2201da177e4SLinus Torvalds /* Send SIGTRAP if we're single-stepping: */ 2211da177e4SLinus Torvalds if (ptrace_cancel_bpt (current)) { 222*7de5f68dSEric W. Biederman send_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *) regs->pc, 2235f50245bSEric W. Biederman current); 2241da177e4SLinus Torvalds } 2251da177e4SLinus Torvalds return; 2261da177e4SLinus Torvalds 2271da177e4SLinus Torvalds give_sigsegv: 2283cf5d076SEric W. Biederman force_sig(SIGSEGV); 2291da177e4SLinus Torvalds } 2301da177e4SLinus Torvalds 2311da177e4SLinus Torvalds asmlinkage void 232b960f303SAl Viro do_rt_sigreturn(struct rt_sigframe __user *frame) 2331da177e4SLinus Torvalds { 234b960f303SAl Viro struct pt_regs *regs = current_pt_regs(); 2351da177e4SLinus Torvalds sigset_t set; 2361da177e4SLinus Torvalds 2371da177e4SLinus Torvalds /* Verify that it's a good ucontext_t before using it */ 23896d4f267SLinus Torvalds if (!access_ok(&frame->uc, sizeof(frame->uc))) 2391da177e4SLinus Torvalds goto give_sigsegv; 2401da177e4SLinus Torvalds if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) 2411da177e4SLinus Torvalds goto give_sigsegv; 2421da177e4SLinus Torvalds 2432561b069SMatt Fleming set_current_blocked(&set); 2441da177e4SLinus Torvalds 245b960f303SAl Viro if (restore_sigcontext(&frame->uc.uc_mcontext, regs)) 2461da177e4SLinus Torvalds goto give_sigsegv; 2471da177e4SLinus Torvalds 2481da177e4SLinus Torvalds /* Send SIGTRAP if we're single-stepping: */ 2491da177e4SLinus Torvalds if (ptrace_cancel_bpt (current)) { 250*7de5f68dSEric W. Biederman send_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *) regs->pc, 2515f50245bSEric W. Biederman current); 2521da177e4SLinus Torvalds } 2531da177e4SLinus Torvalds return; 2541da177e4SLinus Torvalds 2551da177e4SLinus Torvalds give_sigsegv: 2563cf5d076SEric W. Biederman force_sig(SIGSEGV); 2571da177e4SLinus Torvalds } 2581da177e4SLinus Torvalds 2591da177e4SLinus Torvalds 2601da177e4SLinus Torvalds /* 2611da177e4SLinus Torvalds * Set up a signal frame. 2621da177e4SLinus Torvalds */ 2631da177e4SLinus Torvalds 2641da177e4SLinus Torvalds static inline void __user * 265cfd60c07SAl Viro get_sigframe(struct ksignal *ksig, unsigned long sp, size_t frame_size) 2661da177e4SLinus Torvalds { 267cfd60c07SAl Viro return (void __user *)((sigsp(sp, ksig) - frame_size) & -32ul); 2681da177e4SLinus Torvalds } 2691da177e4SLinus Torvalds 2701da177e4SLinus Torvalds static long 2711da177e4SLinus Torvalds setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, 272d9d0738aSAl Viro unsigned long mask, unsigned long sp) 2731da177e4SLinus Torvalds { 274d9d0738aSAl Viro struct switch_stack *sw = (struct switch_stack *)regs - 1; 2751da177e4SLinus Torvalds long i, err = 0; 2761da177e4SLinus Torvalds 2771da177e4SLinus Torvalds err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack); 2781da177e4SLinus Torvalds err |= __put_user(mask, &sc->sc_mask); 2791da177e4SLinus Torvalds err |= __put_user(regs->pc, &sc->sc_pc); 2801da177e4SLinus Torvalds err |= __put_user(8, &sc->sc_ps); 2811da177e4SLinus Torvalds 2821da177e4SLinus Torvalds err |= __put_user(regs->r0 , sc->sc_regs+0); 2831da177e4SLinus Torvalds err |= __put_user(regs->r1 , sc->sc_regs+1); 2841da177e4SLinus Torvalds err |= __put_user(regs->r2 , sc->sc_regs+2); 2851da177e4SLinus Torvalds err |= __put_user(regs->r3 , sc->sc_regs+3); 2861da177e4SLinus Torvalds err |= __put_user(regs->r4 , sc->sc_regs+4); 2871da177e4SLinus Torvalds err |= __put_user(regs->r5 , sc->sc_regs+5); 2881da177e4SLinus Torvalds err |= __put_user(regs->r6 , sc->sc_regs+6); 2891da177e4SLinus Torvalds err |= __put_user(regs->r7 , sc->sc_regs+7); 2901da177e4SLinus Torvalds err |= __put_user(regs->r8 , sc->sc_regs+8); 2911da177e4SLinus Torvalds err |= __put_user(sw->r9 , sc->sc_regs+9); 2921da177e4SLinus Torvalds err |= __put_user(sw->r10 , sc->sc_regs+10); 2931da177e4SLinus Torvalds err |= __put_user(sw->r11 , sc->sc_regs+11); 2941da177e4SLinus Torvalds err |= __put_user(sw->r12 , sc->sc_regs+12); 2951da177e4SLinus Torvalds err |= __put_user(sw->r13 , sc->sc_regs+13); 2961da177e4SLinus Torvalds err |= __put_user(sw->r14 , sc->sc_regs+14); 2971da177e4SLinus Torvalds err |= __put_user(sw->r15 , sc->sc_regs+15); 2981da177e4SLinus Torvalds err |= __put_user(regs->r16, sc->sc_regs+16); 2991da177e4SLinus Torvalds err |= __put_user(regs->r17, sc->sc_regs+17); 3001da177e4SLinus Torvalds err |= __put_user(regs->r18, sc->sc_regs+18); 3011da177e4SLinus Torvalds err |= __put_user(regs->r19, sc->sc_regs+19); 3021da177e4SLinus Torvalds err |= __put_user(regs->r20, sc->sc_regs+20); 3031da177e4SLinus Torvalds err |= __put_user(regs->r21, sc->sc_regs+21); 3041da177e4SLinus Torvalds err |= __put_user(regs->r22, sc->sc_regs+22); 3051da177e4SLinus Torvalds err |= __put_user(regs->r23, sc->sc_regs+23); 3061da177e4SLinus Torvalds err |= __put_user(regs->r24, sc->sc_regs+24); 3071da177e4SLinus Torvalds err |= __put_user(regs->r25, sc->sc_regs+25); 3081da177e4SLinus Torvalds err |= __put_user(regs->r26, sc->sc_regs+26); 3091da177e4SLinus Torvalds err |= __put_user(regs->r27, sc->sc_regs+27); 3101da177e4SLinus Torvalds err |= __put_user(regs->r28, sc->sc_regs+28); 3111da177e4SLinus Torvalds err |= __put_user(regs->gp , sc->sc_regs+29); 3121da177e4SLinus Torvalds err |= __put_user(sp, sc->sc_regs+30); 3131da177e4SLinus Torvalds err |= __put_user(0, sc->sc_regs+31); 3141da177e4SLinus Torvalds 3151da177e4SLinus Torvalds for (i = 0; i < 31; i++) 3161da177e4SLinus Torvalds err |= __put_user(sw->fp[i], sc->sc_fpregs+i); 3171da177e4SLinus Torvalds err |= __put_user(0, sc->sc_fpregs+31); 3181da177e4SLinus Torvalds err |= __put_user(sw->fp[31], &sc->sc_fpcr); 3191da177e4SLinus Torvalds 3201da177e4SLinus Torvalds err |= __put_user(regs->trap_a0, &sc->sc_traparg_a0); 3211da177e4SLinus Torvalds err |= __put_user(regs->trap_a1, &sc->sc_traparg_a1); 3221da177e4SLinus Torvalds err |= __put_user(regs->trap_a2, &sc->sc_traparg_a2); 3231da177e4SLinus Torvalds 3241da177e4SLinus Torvalds return err; 3251da177e4SLinus Torvalds } 3261da177e4SLinus Torvalds 327b927b3e2SRichard Henderson static int 328cfd60c07SAl Viro setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) 3291da177e4SLinus Torvalds { 3301da177e4SLinus Torvalds unsigned long oldsp, r26, err = 0; 3311da177e4SLinus Torvalds struct sigframe __user *frame; 3321da177e4SLinus Torvalds 3331da177e4SLinus Torvalds oldsp = rdusp(); 334cfd60c07SAl Viro frame = get_sigframe(ksig, oldsp, sizeof(*frame)); 33596d4f267SLinus Torvalds if (!access_ok(frame, sizeof(*frame))) 336cbdfb9ffSAl Viro return -EFAULT; 3371da177e4SLinus Torvalds 338d9d0738aSAl Viro err |= setup_sigcontext(&frame->sc, regs, set->sig[0], oldsp); 3391da177e4SLinus Torvalds if (err) 340cbdfb9ffSAl Viro return -EFAULT; 3411da177e4SLinus Torvalds 3421da177e4SLinus Torvalds /* Set up to return from userspace. If provided, use a stub 3431da177e4SLinus Torvalds already in userspace. */ 344cfd60c07SAl Viro r26 = (unsigned long) ksig->ka.ka_restorer; 345cfd60c07SAl Viro if (!r26) { 3461da177e4SLinus Torvalds err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0); 3471da177e4SLinus Torvalds err |= __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1); 3481da177e4SLinus Torvalds err |= __put_user(INSN_CALLSYS, frame->retcode+2); 3491da177e4SLinus Torvalds imb(); 3501da177e4SLinus Torvalds r26 = (unsigned long) frame->retcode; 3511da177e4SLinus Torvalds } 3521da177e4SLinus Torvalds 3531da177e4SLinus Torvalds /* Check that everything was written properly. */ 3541da177e4SLinus Torvalds if (err) 355cbdfb9ffSAl Viro return err; 3561da177e4SLinus Torvalds 3571da177e4SLinus Torvalds /* "Return" to the handler */ 3581da177e4SLinus Torvalds regs->r26 = r26; 359cfd60c07SAl Viro regs->r27 = regs->pc = (unsigned long) ksig->ka.sa.sa_handler; 360cfd60c07SAl Viro regs->r16 = ksig->sig; /* a0: signal number */ 3611da177e4SLinus Torvalds regs->r17 = 0; /* a1: exception code */ 3621da177e4SLinus Torvalds regs->r18 = (unsigned long) &frame->sc; /* a2: sigcontext pointer */ 3631da177e4SLinus Torvalds wrusp((unsigned long) frame); 3641da177e4SLinus Torvalds 3651da177e4SLinus Torvalds #if DEBUG_SIG 3661da177e4SLinus Torvalds printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", 3671da177e4SLinus Torvalds current->comm, current->pid, frame, regs->pc, regs->r26); 3681da177e4SLinus Torvalds #endif 369b927b3e2SRichard Henderson return 0; 3701da177e4SLinus Torvalds } 3711da177e4SLinus Torvalds 372b927b3e2SRichard Henderson static int 373cfd60c07SAl Viro setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) 3741da177e4SLinus Torvalds { 3751da177e4SLinus Torvalds unsigned long oldsp, r26, err = 0; 3761da177e4SLinus Torvalds struct rt_sigframe __user *frame; 3771da177e4SLinus Torvalds 3781da177e4SLinus Torvalds oldsp = rdusp(); 379cfd60c07SAl Viro frame = get_sigframe(ksig, oldsp, sizeof(*frame)); 38096d4f267SLinus Torvalds if (!access_ok(frame, sizeof(*frame))) 381cbdfb9ffSAl Viro return -EFAULT; 3821da177e4SLinus Torvalds 383cfd60c07SAl Viro err |= copy_siginfo_to_user(&frame->info, &ksig->info); 3841da177e4SLinus Torvalds 3851da177e4SLinus Torvalds /* Create the ucontext. */ 3861da177e4SLinus Torvalds err |= __put_user(0, &frame->uc.uc_flags); 3871da177e4SLinus Torvalds err |= __put_user(0, &frame->uc.uc_link); 3881da177e4SLinus Torvalds err |= __put_user(set->sig[0], &frame->uc.uc_osf_sigmask); 38950ececcfSAl Viro err |= __save_altstack(&frame->uc.uc_stack, oldsp); 390d9d0738aSAl Viro err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, 3911da177e4SLinus Torvalds set->sig[0], oldsp); 3921da177e4SLinus Torvalds err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 3931da177e4SLinus Torvalds if (err) 394cbdfb9ffSAl Viro return -EFAULT; 3951da177e4SLinus Torvalds 3961da177e4SLinus Torvalds /* Set up to return from userspace. If provided, use a stub 3971da177e4SLinus Torvalds already in userspace. */ 398cfd60c07SAl Viro r26 = (unsigned long) ksig->ka.ka_restorer; 399cfd60c07SAl Viro if (!r26) { 4001da177e4SLinus Torvalds err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0); 4011da177e4SLinus Torvalds err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn, 4021da177e4SLinus Torvalds frame->retcode+1); 4031da177e4SLinus Torvalds err |= __put_user(INSN_CALLSYS, frame->retcode+2); 4041da177e4SLinus Torvalds imb(); 4051da177e4SLinus Torvalds r26 = (unsigned long) frame->retcode; 4061da177e4SLinus Torvalds } 4071da177e4SLinus Torvalds 4081da177e4SLinus Torvalds if (err) 409cbdfb9ffSAl Viro return -EFAULT; 4101da177e4SLinus Torvalds 4111da177e4SLinus Torvalds /* "Return" to the handler */ 4121da177e4SLinus Torvalds regs->r26 = r26; 413cfd60c07SAl Viro regs->r27 = regs->pc = (unsigned long) ksig->ka.sa.sa_handler; 414cfd60c07SAl Viro regs->r16 = ksig->sig; /* a0: signal number */ 4151da177e4SLinus Torvalds regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */ 4161da177e4SLinus Torvalds regs->r18 = (unsigned long) &frame->uc; /* a2: ucontext pointer */ 4171da177e4SLinus Torvalds wrusp((unsigned long) frame); 4181da177e4SLinus Torvalds 4191da177e4SLinus Torvalds #if DEBUG_SIG 4201da177e4SLinus Torvalds printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", 4211da177e4SLinus Torvalds current->comm, current->pid, frame, regs->pc, regs->r26); 4221da177e4SLinus Torvalds #endif 4231da177e4SLinus Torvalds 424b927b3e2SRichard Henderson return 0; 4251da177e4SLinus Torvalds } 4261da177e4SLinus Torvalds 4271da177e4SLinus Torvalds 4281da177e4SLinus Torvalds /* 4291da177e4SLinus Torvalds * OK, we're invoking a handler. 4301da177e4SLinus Torvalds */ 431cbdfb9ffSAl Viro static inline void 432cfd60c07SAl Viro handle_signal(struct ksignal *ksig, struct pt_regs *regs) 4331da177e4SLinus Torvalds { 434b7f9a11aSAl Viro sigset_t *oldset = sigmask_to_save(); 435b927b3e2SRichard Henderson int ret; 436b927b3e2SRichard Henderson 437cfd60c07SAl Viro if (ksig->ka.sa.sa_flags & SA_SIGINFO) 438cfd60c07SAl Viro ret = setup_rt_frame(ksig, oldset, regs); 4391da177e4SLinus Torvalds else 440cfd60c07SAl Viro ret = setup_frame(ksig, oldset, regs); 4411da177e4SLinus Torvalds 442cfd60c07SAl Viro signal_setup_done(ret, ksig, 0); 443b927b3e2SRichard Henderson } 444b927b3e2SRichard Henderson 4451da177e4SLinus Torvalds static inline void 4461da177e4SLinus Torvalds syscall_restart(unsigned long r0, unsigned long r19, 4471da177e4SLinus Torvalds struct pt_regs *regs, struct k_sigaction *ka) 4481da177e4SLinus Torvalds { 4491da177e4SLinus Torvalds switch (regs->r0) { 4501da177e4SLinus Torvalds case ERESTARTSYS: 4511da177e4SLinus Torvalds if (!(ka->sa.sa_flags & SA_RESTART)) { 4521da177e4SLinus Torvalds case ERESTARTNOHAND: 4531da177e4SLinus Torvalds regs->r0 = EINTR; 4541da177e4SLinus Torvalds break; 4551da177e4SLinus Torvalds } 456df561f66SGustavo A. R. Silva fallthrough; 4571da177e4SLinus Torvalds case ERESTARTNOINTR: 4581da177e4SLinus Torvalds regs->r0 = r0; /* reset v0 and a3 and replay syscall */ 4591da177e4SLinus Torvalds regs->r19 = r19; 4601da177e4SLinus Torvalds regs->pc -= 4; 4611da177e4SLinus Torvalds break; 4621da177e4SLinus Torvalds case ERESTART_RESTARTBLOCK: 4631da177e4SLinus Torvalds regs->r0 = EINTR; 4641da177e4SLinus Torvalds break; 4651da177e4SLinus Torvalds } 4661da177e4SLinus Torvalds } 4671da177e4SLinus Torvalds 4681da177e4SLinus Torvalds 4691da177e4SLinus Torvalds /* 4701da177e4SLinus Torvalds * Note that 'init' is a special process: it doesn't get signals it doesn't 4711da177e4SLinus Torvalds * want to handle. Thus you cannot kill init even with a SIGKILL even by 4721da177e4SLinus Torvalds * mistake. 4731da177e4SLinus Torvalds * 4741da177e4SLinus Torvalds * Note that we go through the signals twice: once to check the signals that 4751da177e4SLinus Torvalds * the kernel can handle, and then we build all the user-level signal handling 4761da177e4SLinus Torvalds * stack-frames in one go after that. 4771da177e4SLinus Torvalds * 4781da177e4SLinus Torvalds * "r0" and "r19" are the registers we need to restore for system call 4791da177e4SLinus Torvalds * restart. "r0" is also used as an indicator whether we can restart at 4801da177e4SLinus Torvalds * all (if we get here from anything but a syscall return, it will be 0) 4811da177e4SLinus Torvalds */ 482b927b3e2SRichard Henderson static void 483d9d0738aSAl Viro do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19) 4841da177e4SLinus Torvalds { 4851da177e4SLinus Torvalds unsigned long single_stepping = ptrace_cancel_bpt(current); 486cfd60c07SAl Viro struct ksignal ksig; 4871da177e4SLinus Torvalds 4881da177e4SLinus Torvalds /* This lets the debugger run, ... */ 489cfd60c07SAl Viro if (get_signal(&ksig)) { 4901da177e4SLinus Torvalds /* ... so re-check the single stepping. */ 4911da177e4SLinus Torvalds single_stepping |= ptrace_cancel_bpt(current); 4921da177e4SLinus Torvalds /* Whee! Actually deliver the signal. */ 493b927b3e2SRichard Henderson if (r0) 494cfd60c07SAl Viro syscall_restart(r0, r19, regs, &ksig.ka); 495cfd60c07SAl Viro handle_signal(&ksig, regs); 496cfd60c07SAl Viro } else { 497cfd60c07SAl Viro single_stepping |= ptrace_cancel_bpt(current); 4981da177e4SLinus Torvalds if (r0) { 4991da177e4SLinus Torvalds switch (regs->r0) { 5001da177e4SLinus Torvalds case ERESTARTNOHAND: 5011da177e4SLinus Torvalds case ERESTARTSYS: 5021da177e4SLinus Torvalds case ERESTARTNOINTR: 5031da177e4SLinus Torvalds /* Reset v0 and a3 and replay syscall. */ 5041da177e4SLinus Torvalds regs->r0 = r0; 5051da177e4SLinus Torvalds regs->r19 = r19; 5061da177e4SLinus Torvalds regs->pc -= 4; 5071da177e4SLinus Torvalds break; 5081da177e4SLinus Torvalds case ERESTART_RESTARTBLOCK: 509cfd60c07SAl Viro /* Set v0 to the restart_syscall and replay */ 5101da177e4SLinus Torvalds regs->r0 = __NR_restart_syscall; 5111da177e4SLinus Torvalds regs->pc -= 4; 5121da177e4SLinus Torvalds break; 5131da177e4SLinus Torvalds } 5141da177e4SLinus Torvalds } 51551a7b448SAl Viro restore_saved_sigmask(); 516cfd60c07SAl Viro } 5171da177e4SLinus Torvalds if (single_stepping) 5181da177e4SLinus Torvalds ptrace_set_bpt(current); /* re-set breakpoint */ 5191da177e4SLinus Torvalds } 5201da177e4SLinus Torvalds 5211da177e4SLinus Torvalds void 522cb450766SAl Viro do_work_pending(struct pt_regs *regs, unsigned long thread_flags, 523b927b3e2SRichard Henderson unsigned long r0, unsigned long r19) 5241da177e4SLinus Torvalds { 5256972d6f2SAl Viro do { 5266972d6f2SAl Viro if (thread_flags & _TIF_NEED_RESCHED) { 5276972d6f2SAl Viro schedule(); 5286972d6f2SAl Viro } else { 5296972d6f2SAl Viro local_irq_enable(); 5305a9a8897SJens Axboe if (thread_flags & (_TIF_SIGPENDING|_TIF_NOTIFY_SIGNAL)) { 531d9d0738aSAl Viro do_signal(regs, r0, r19); 5326972d6f2SAl Viro r0 = 0; 5336972d6f2SAl Viro } else { 534d0420c83SDavid Howells tracehook_notify_resume(regs); 535d0420c83SDavid Howells } 5361da177e4SLinus Torvalds } 5376972d6f2SAl Viro local_irq_disable(); 5386972d6f2SAl Viro thread_flags = current_thread_info()->flags; 5396972d6f2SAl Viro } while (thread_flags & _TIF_WORK_MASK); 5406972d6f2SAl Viro } 541