root/arch/openrisc/kernel/signal.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. restore_sigcontext
  2. _sys_rt_sigreturn
  3. setup_sigcontext
  4. align_sigframe
  5. get_sigframe
  6. setup_rt_frame
  7. handle_signal
  8. do_signal
  9. do_work_pending

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

/* [<][>][^][v][top][bottom][index][help] */