linux/arch/frv/kernel/signal.c
<<
>>
Prefs
   1/* signal.c: FRV specific bits of signal handling
   2 *
   3 * Copyright (C) 2003-5 Red Hat, Inc. All Rights Reserved.
   4 * Written by David Howells (dhowells@redhat.com)
   5 * - Derived from arch/m68k/kernel/signal.c
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU General Public License
   9 * as published by the Free Software Foundation; either version
  10 * 2 of the License, or (at your option) any later version.
  11 */
  12
  13#include <linux/sched.h>
  14#include <linux/mm.h>
  15#include <linux/smp.h>
  16#include <linux/kernel.h>
  17#include <linux/signal.h>
  18#include <linux/errno.h>
  19#include <linux/wait.h>
  20#include <linux/ptrace.h>
  21#include <linux/unistd.h>
  22#include <linux/personality.h>
  23#include <linux/freezer.h>
  24#include <linux/tracehook.h>
  25#include <asm/ucontext.h>
  26#include <asm/uaccess.h>
  27#include <asm/cacheflush.h>
  28
  29#define DEBUG_SIG 0
  30
  31struct fdpic_func_descriptor {
  32        unsigned long   text;
  33        unsigned long   GOT;
  34};
  35
  36/*
  37 * Atomically swap in the new signal mask, and wait for a signal.
  38 */
  39asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
  40{
  41        sigset_t blocked;
  42        siginitset(&blocked, mask);
  43        return sigsuspend(&blocked);
  44}
  45
  46asmlinkage int sys_sigaction(int sig,
  47                             const struct old_sigaction __user *act,
  48                             struct old_sigaction __user *oact)
  49{
  50        struct k_sigaction new_ka, old_ka;
  51        int ret;
  52
  53        if (act) {
  54                old_sigset_t mask;
  55                if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
  56                    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
  57                    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
  58                    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
  59                    __get_user(mask, &act->sa_mask))
  60                        return -EFAULT;
  61                siginitset(&new_ka.sa.sa_mask, mask);
  62        }
  63
  64        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
  65
  66        if (!ret && oact) {
  67                if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
  68                    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
  69                    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
  70                    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
  71                    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
  72                        return -EFAULT;
  73        }
  74
  75        return ret;
  76}
  77
  78asmlinkage
  79int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
  80{
  81        return do_sigaltstack(uss, uoss, __frame->sp);
  82}
  83
  84
  85/*
  86 * Do a signal return; undo the signal stack.
  87 */
  88
  89struct sigframe
  90{
  91        __sigrestore_t pretcode;
  92        int sig;
  93        struct sigcontext sc;
  94        unsigned long extramask[_NSIG_WORDS-1];
  95        uint32_t retcode[2];
  96};
  97
  98struct rt_sigframe
  99{
 100        __sigrestore_t pretcode;
 101        int sig;
 102        struct siginfo __user *pinfo;
 103        void __user *puc;
 104        struct siginfo info;
 105        struct ucontext uc;
 106        uint32_t retcode[2];
 107};
 108
 109static int restore_sigcontext(struct sigcontext __user *sc, int *_gr8)
 110{
 111        struct user_context *user = current->thread.user;
 112        unsigned long tbr, psr;
 113
 114        /* Always make any pending restarted system calls return -EINTR */
 115        current_thread_info()->restart_block.fn = do_no_restart_syscall;
 116
 117        tbr = user->i.tbr;
 118        psr = user->i.psr;
 119        if (copy_from_user(user, &sc->sc_context, sizeof(sc->sc_context)))
 120                goto badframe;
 121        user->i.tbr = tbr;
 122        user->i.psr = psr;
 123
 124        restore_user_regs(user);
 125
 126        user->i.syscallno = -1;         /* disable syscall checks */
 127
 128        *_gr8 = user->i.gr[8];
 129        return 0;
 130
 131 badframe:
 132        return 1;
 133}
 134
 135asmlinkage int sys_sigreturn(void)
 136{
 137        struct sigframe __user *frame = (struct sigframe __user *) __frame->sp;
 138        sigset_t set;
 139        int gr8;
 140
 141        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 142                goto badframe;
 143        if (__get_user(set.sig[0], &frame->sc.sc_oldmask))
 144                goto badframe;
 145
 146        if (_NSIG_WORDS > 1 &&
 147            __copy_from_user(&set.sig[1], &frame->extramask, sizeof(frame->extramask)))
 148                goto badframe;
 149
 150        set_current_blocked(&set);
 151
 152        if (restore_sigcontext(&frame->sc, &gr8))
 153                goto badframe;
 154        return gr8;
 155
 156 badframe:
 157        force_sig(SIGSEGV, current);
 158        return 0;
 159}
 160
 161asmlinkage int sys_rt_sigreturn(void)
 162{
 163        struct rt_sigframe __user *frame = (struct rt_sigframe __user *) __frame->sp;
 164        sigset_t set;
 165        int gr8;
 166
 167        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 168                goto badframe;
 169        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
 170                goto badframe;
 171
 172        set_current_blocked(&set);
 173
 174        if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8))
 175                goto badframe;
 176
 177        if (do_sigaltstack(&frame->uc.uc_stack, NULL, __frame->sp) == -EFAULT)
 178                goto badframe;
 179
 180        return gr8;
 181
 182badframe:
 183        force_sig(SIGSEGV, current);
 184        return 0;
 185}
 186
 187/*
 188 * Set up a signal frame
 189 */
 190static int setup_sigcontext(struct sigcontext __user *sc, unsigned long mask)
 191{
 192        save_user_regs(current->thread.user);
 193
 194        if (copy_to_user(&sc->sc_context, current->thread.user, sizeof(sc->sc_context)) != 0)
 195                goto badframe;
 196
 197        /* non-iBCS2 extensions.. */
 198        if (__put_user(mask, &sc->sc_oldmask) < 0)
 199                goto badframe;
 200
 201        return 0;
 202
 203 badframe:
 204        return 1;
 205}
 206
 207/*****************************************************************************/
 208/*
 209 * Determine which stack to use..
 210 */
 211static inline void __user *get_sigframe(struct k_sigaction *ka,
 212                                        size_t frame_size)
 213{
 214        unsigned long sp;
 215
 216        /* Default to using normal stack */
 217        sp = __frame->sp;
 218
 219        /* This is the X/Open sanctioned signal stack switching.  */
 220        if (ka->sa.sa_flags & SA_ONSTACK) {
 221                if (! sas_ss_flags(sp))
 222                        sp = current->sas_ss_sp + current->sas_ss_size;
 223        }
 224
 225        return (void __user *) ((sp - frame_size) & ~7UL);
 226
 227} /* end get_sigframe() */
 228
 229/*****************************************************************************/
 230/*
 231 *
 232 */
 233static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
 234{
 235        struct sigframe __user *frame;
 236        int rsig;
 237
 238        set_fs(USER_DS);
 239
 240        frame = get_sigframe(ka, sizeof(*frame));
 241
 242        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 243                goto give_sigsegv;
 244
 245        rsig = sig;
 246        if (sig < 32 &&
 247            __current_thread_info->exec_domain &&
 248            __current_thread_info->exec_domain->signal_invmap)
 249                rsig = __current_thread_info->exec_domain->signal_invmap[sig];
 250
 251        if (__put_user(rsig, &frame->sig) < 0)
 252                goto give_sigsegv;
 253
 254        if (setup_sigcontext(&frame->sc, set->sig[0]))
 255                goto give_sigsegv;
 256
 257        if (_NSIG_WORDS > 1) {
 258                if (__copy_to_user(frame->extramask, &set->sig[1],
 259                                   sizeof(frame->extramask)))
 260                        goto give_sigsegv;
 261        }
 262
 263        /* Set up to return from userspace.  If provided, use a stub
 264         * already in userspace.  */
 265        if (ka->sa.sa_flags & SA_RESTORER) {
 266                if (__put_user(ka->sa.sa_restorer, &frame->pretcode) < 0)
 267                        goto give_sigsegv;
 268        }
 269        else {
 270                /* Set up the following code on the stack:
 271                 *      setlos  #__NR_sigreturn,gr7
 272                 *      tira    gr0,0
 273                 */
 274                if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) ||
 275                    __put_user(0x8efc0000|__NR_sigreturn, &frame->retcode[0]) ||
 276                    __put_user(0xc0700000, &frame->retcode[1]))
 277                        goto give_sigsegv;
 278
 279                flush_icache_range((unsigned long) frame->retcode,
 280                                   (unsigned long) (frame->retcode + 2));
 281        }
 282
 283        /* Set up registers for the signal handler */
 284        if (current->personality & FDPIC_FUNCPTRS) {
 285                struct fdpic_func_descriptor __user *funcptr =
 286                        (struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
 287                struct fdpic_func_descriptor desc;
 288                if (copy_from_user(&desc, funcptr, sizeof(desc)))
 289                        goto give_sigsegv;
 290                __frame->pc = desc.text;
 291                __frame->gr15 = desc.GOT;
 292        } else {
 293                __frame->pc   = (unsigned long) ka->sa.sa_handler;
 294                __frame->gr15 = 0;
 295        }
 296
 297        __frame->sp   = (unsigned long) frame;
 298        __frame->lr   = (unsigned long) &frame->retcode;
 299        __frame->gr8  = sig;
 300
 301        /* the tracer may want to single-step inside the handler */
 302        if (test_thread_flag(TIF_SINGLESTEP))
 303                ptrace_notify(SIGTRAP);
 304
 305#if DEBUG_SIG
 306        printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
 307               sig, current->comm, current->pid, frame, __frame->pc,
 308               frame->pretcode);
 309#endif
 310
 311        return 0;
 312
 313give_sigsegv:
 314        force_sigsegv(sig, current);
 315        return -EFAULT;
 316
 317} /* end setup_frame() */
 318
 319/*****************************************************************************/
 320/*
 321 *
 322 */
 323static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 324                          sigset_t *set)
 325{
 326        struct rt_sigframe __user *frame;
 327        int rsig;
 328
 329        set_fs(USER_DS);
 330
 331        frame = get_sigframe(ka, sizeof(*frame));
 332
 333        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 334                goto give_sigsegv;
 335
 336        rsig = sig;
 337        if (sig < 32 &&
 338            __current_thread_info->exec_domain &&
 339            __current_thread_info->exec_domain->signal_invmap)
 340                rsig = __current_thread_info->exec_domain->signal_invmap[sig];
 341
 342        if (__put_user(rsig,            &frame->sig) ||
 343            __put_user(&frame->info,    &frame->pinfo) ||
 344            __put_user(&frame->uc,      &frame->puc))
 345                goto give_sigsegv;
 346
 347        if (copy_siginfo_to_user(&frame->info, info))
 348                goto give_sigsegv;
 349
 350        /* Create the ucontext.  */
 351        if (__put_user(0, &frame->uc.uc_flags) ||
 352            __put_user(NULL, &frame->uc.uc_link) ||
 353            __put_user((void __user *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) ||
 354            __put_user(sas_ss_flags(__frame->sp), &frame->uc.uc_stack.ss_flags) ||
 355            __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size))
 356                goto give_sigsegv;
 357
 358        if (setup_sigcontext(&frame->uc.uc_mcontext, set->sig[0]))
 359                goto give_sigsegv;
 360
 361        if (__copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)))
 362                goto give_sigsegv;
 363
 364        /* Set up to return from userspace.  If provided, use a stub
 365         * already in userspace.  */
 366        if (ka->sa.sa_flags & SA_RESTORER) {
 367                if (__put_user(ka->sa.sa_restorer, &frame->pretcode))
 368                        goto give_sigsegv;
 369        }
 370        else {
 371                /* Set up the following code on the stack:
 372                 *      setlos  #__NR_sigreturn,gr7
 373                 *      tira    gr0,0
 374                 */
 375                if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) ||
 376                    __put_user(0x8efc0000|__NR_rt_sigreturn, &frame->retcode[0]) ||
 377                    __put_user(0xc0700000, &frame->retcode[1]))
 378                        goto give_sigsegv;
 379
 380                flush_icache_range((unsigned long) frame->retcode,
 381                                   (unsigned long) (frame->retcode + 2));
 382        }
 383
 384        /* Set up registers for signal handler */
 385        if (current->personality & FDPIC_FUNCPTRS) {
 386                struct fdpic_func_descriptor __user *funcptr =
 387                        (struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
 388                struct fdpic_func_descriptor desc;
 389                if (copy_from_user(&desc, funcptr, sizeof(desc)))
 390                        goto give_sigsegv;
 391                __frame->pc = desc.text;
 392                __frame->gr15 = desc.GOT;
 393        } else {
 394                __frame->pc   = (unsigned long) ka->sa.sa_handler;
 395                __frame->gr15 = 0;
 396        }
 397
 398        __frame->sp  = (unsigned long) frame;
 399        __frame->lr  = (unsigned long) &frame->retcode;
 400        __frame->gr8 = sig;
 401        __frame->gr9 = (unsigned long) &frame->info;
 402
 403        /* the tracer may want to single-step inside the handler */
 404        if (test_thread_flag(TIF_SINGLESTEP))
 405                ptrace_notify(SIGTRAP);
 406
 407#if DEBUG_SIG
 408        printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
 409               sig, current->comm, current->pid, frame, __frame->pc,
 410               frame->pretcode);
 411#endif
 412
 413        return 0;
 414
 415give_sigsegv:
 416        force_sigsegv(sig, current);
 417        return -EFAULT;
 418
 419} /* end setup_rt_frame() */
 420
 421/*****************************************************************************/
 422/*
 423 * OK, we're invoking a handler
 424 */
 425static void handle_signal(unsigned long sig, siginfo_t *info,
 426                         struct k_sigaction *ka)
 427{
 428        sigset_t *oldset = sigmask_to_save();
 429        int ret;
 430
 431        /* Are we from a system call? */
 432        if (__frame->syscallno != -1) {
 433                /* If so, check system call restarting.. */
 434                switch (__frame->gr8) {
 435                case -ERESTART_RESTARTBLOCK:
 436                case -ERESTARTNOHAND:
 437                        __frame->gr8 = -EINTR;
 438                        break;
 439
 440                case -ERESTARTSYS:
 441                        if (!(ka->sa.sa_flags & SA_RESTART)) {
 442                                __frame->gr8 = -EINTR;
 443                                break;
 444                        }
 445
 446                        /* fallthrough */
 447                case -ERESTARTNOINTR:
 448                        __frame->gr8 = __frame->orig_gr8;
 449                        __frame->pc -= 4;
 450                }
 451                __frame->syscallno = -1;
 452        }
 453
 454        /* Set up the stack frame */
 455        if (ka->sa.sa_flags & SA_SIGINFO)
 456                ret = setup_rt_frame(sig, ka, info, oldset);
 457        else
 458                ret = setup_frame(sig, ka, oldset);
 459
 460        if (ret)
 461                return;
 462
 463        signal_delivered(sig, info, ka, __frame,
 464                                 test_thread_flag(TIF_SINGLESTEP));
 465} /* end handle_signal() */
 466
 467/*****************************************************************************/
 468/*
 469 * Note that 'init' is a special process: it doesn't get signals it doesn't
 470 * want to handle. Thus you cannot kill init even with a SIGKILL even by
 471 * mistake.
 472 */
 473static void do_signal(void)
 474{
 475        struct k_sigaction ka;
 476        siginfo_t info;
 477        int signr;
 478
 479        signr = get_signal_to_deliver(&info, &ka, __frame, NULL);
 480        if (signr > 0) {
 481                handle_signal(signr, &info, &ka);
 482                return;
 483        }
 484
 485        /* Did we come from a system call? */
 486        if (__frame->syscallno != -1) {
 487                /* Restart the system call - no handlers present */
 488                switch (__frame->gr8) {
 489                case -ERESTARTNOHAND:
 490                case -ERESTARTSYS:
 491                case -ERESTARTNOINTR:
 492                        __frame->gr8 = __frame->orig_gr8;
 493                        __frame->pc -= 4;
 494                        break;
 495
 496                case -ERESTART_RESTARTBLOCK:
 497                        __frame->gr7 = __NR_restart_syscall;
 498                        __frame->pc -= 4;
 499                        break;
 500                }
 501                __frame->syscallno = -1;
 502        }
 503
 504        /* if there's no signal to deliver, we just put the saved sigmask
 505         * back */
 506        restore_saved_sigmask();
 507} /* end do_signal() */
 508
 509/*****************************************************************************/
 510/*
 511 * notification of userspace execution resumption
 512 * - triggered by the TIF_WORK_MASK flags
 513 */
 514asmlinkage void do_notify_resume(__u32 thread_info_flags)
 515{
 516        /* pending single-step? */
 517        if (thread_info_flags & _TIF_SINGLESTEP)
 518                clear_thread_flag(TIF_SINGLESTEP);
 519
 520        /* deal with pending signal delivery */
 521        if (thread_info_flags & _TIF_SIGPENDING)
 522                do_signal();
 523
 524        /* deal with notification on about to resume userspace execution */
 525        if (thread_info_flags & _TIF_NOTIFY_RESUME) {
 526                clear_thread_flag(TIF_NOTIFY_RESUME);
 527                tracehook_notify_resume(__frame);
 528        }
 529
 530} /* end do_notify_resume() */
 531