linux/arch/mips/kernel/signal32.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 1991, 1992  Linus Torvalds
   7 * Copyright (C) 1994 - 2000, 2006  Ralf Baechle
   8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
   9 */
  10#include <linux/cache.h>
  11#include <linux/compat.h>
  12#include <linux/sched.h>
  13#include <linux/mm.h>
  14#include <linux/smp.h>
  15#include <linux/kernel.h>
  16#include <linux/signal.h>
  17#include <linux/syscalls.h>
  18#include <linux/errno.h>
  19#include <linux/wait.h>
  20#include <linux/ptrace.h>
  21#include <linux/suspend.h>
  22#include <linux/compiler.h>
  23#include <linux/uaccess.h>
  24
  25#include <asm/abi.h>
  26#include <asm/asm.h>
  27#include <asm/compat-signal.h>
  28#include <linux/bitops.h>
  29#include <asm/cacheflush.h>
  30#include <asm/sim.h>
  31#include <asm/ucontext.h>
  32#include <asm/fpu.h>
  33#include <asm/war.h>
  34#include <asm/vdso.h>
  35#include <asm/dsp.h>
  36
  37#include "signal-common.h"
  38
  39static int (*save_fp_context32)(struct sigcontext32 __user *sc);
  40static int (*restore_fp_context32)(struct sigcontext32 __user *sc);
  41
  42extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc);
  43extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc);
  44
  45/*
  46 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
  47 */
  48#define __NR_O32_restart_syscall        4253
  49
  50/* 32-bit compatibility types */
  51
  52typedef unsigned int __sighandler32_t;
  53typedef void (*vfptr_t)(void);
  54
  55struct ucontext32 {
  56        u32                 uc_flags;
  57        s32                 uc_link;
  58        compat_stack_t      uc_stack;
  59        struct sigcontext32 uc_mcontext;
  60        compat_sigset_t     uc_sigmask;   /* mask last for extensibility */
  61};
  62
  63struct sigframe32 {
  64        u32 sf_ass[4];          /* argument save space for o32 */
  65        u32 sf_pad[2];          /* Was: signal trampoline */
  66        struct sigcontext32 sf_sc;
  67        compat_sigset_t sf_mask;
  68};
  69
  70struct rt_sigframe32 {
  71        u32 rs_ass[4];                  /* argument save space for o32 */
  72        u32 rs_pad[2];                  /* Was: signal trampoline */
  73        compat_siginfo_t rs_info;
  74        struct ucontext32 rs_uc;
  75};
  76
  77/*
  78 * Thread saved context copy to/from a signal context presumed to be on the
  79 * user stack, and therefore accessed with appropriate macros from uaccess.h.
  80 */
  81static int copy_fp_to_sigcontext32(struct sigcontext32 __user *sc)
  82{
  83        int i;
  84        int err = 0;
  85        int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1;
  86
  87        for (i = 0; i < NUM_FPU_REGS; i += inc) {
  88                err |=
  89                    __put_user(get_fpr64(&current->thread.fpu.fpr[i], 0),
  90                               &sc->sc_fpregs[i]);
  91        }
  92        err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
  93
  94        return err;
  95}
  96
  97static int copy_fp_from_sigcontext32(struct sigcontext32 __user *sc)
  98{
  99        int i;
 100        int err = 0;
 101        int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1;
 102        u64 fpr_val;
 103
 104        for (i = 0; i < NUM_FPU_REGS; i += inc) {
 105                err |= __get_user(fpr_val, &sc->sc_fpregs[i]);
 106                set_fpr64(&current->thread.fpu.fpr[i], 0, fpr_val);
 107        }
 108        err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
 109
 110        return err;
 111}
 112
 113/*
 114 * sigcontext handlers
 115 */
 116static int protected_save_fp_context32(struct sigcontext32 __user *sc)
 117{
 118        int err;
 119        while (1) {
 120                lock_fpu_owner();
 121                if (is_fpu_owner()) {
 122                        err = save_fp_context32(sc);
 123                        unlock_fpu_owner();
 124                } else {
 125                        unlock_fpu_owner();
 126                        err = copy_fp_to_sigcontext32(sc);
 127                }
 128                if (likely(!err))
 129                        break;
 130                /* touch the sigcontext and try again */
 131                err = __put_user(0, &sc->sc_fpregs[0]) |
 132                        __put_user(0, &sc->sc_fpregs[31]) |
 133                        __put_user(0, &sc->sc_fpc_csr);
 134                if (err)
 135                        break;  /* really bad sigcontext */
 136        }
 137        return err;
 138}
 139
 140static int protected_restore_fp_context32(struct sigcontext32 __user *sc)
 141{
 142        int err, tmp __maybe_unused;
 143        while (1) {
 144                lock_fpu_owner();
 145                if (is_fpu_owner()) {
 146                        err = restore_fp_context32(sc);
 147                        unlock_fpu_owner();
 148                } else {
 149                        unlock_fpu_owner();
 150                        err = copy_fp_from_sigcontext32(sc);
 151                }
 152                if (likely(!err))
 153                        break;
 154                /* touch the sigcontext and try again */
 155                err = __get_user(tmp, &sc->sc_fpregs[0]) |
 156                        __get_user(tmp, &sc->sc_fpregs[31]) |
 157                        __get_user(tmp, &sc->sc_fpc_csr);
 158                if (err)
 159                        break;  /* really bad sigcontext */
 160        }
 161        return err;
 162}
 163
 164static int setup_sigcontext32(struct pt_regs *regs,
 165                              struct sigcontext32 __user *sc)
 166{
 167        int err = 0;
 168        int i;
 169        u32 used_math;
 170
 171        err |= __put_user(regs->cp0_epc, &sc->sc_pc);
 172
 173        err |= __put_user(0, &sc->sc_regs[0]);
 174        for (i = 1; i < 32; i++)
 175                err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
 176
 177        err |= __put_user(regs->hi, &sc->sc_mdhi);
 178        err |= __put_user(regs->lo, &sc->sc_mdlo);
 179        if (cpu_has_dsp) {
 180                err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
 181                err |= __put_user(mfhi1(), &sc->sc_hi1);
 182                err |= __put_user(mflo1(), &sc->sc_lo1);
 183                err |= __put_user(mfhi2(), &sc->sc_hi2);
 184                err |= __put_user(mflo2(), &sc->sc_lo2);
 185                err |= __put_user(mfhi3(), &sc->sc_hi3);
 186                err |= __put_user(mflo3(), &sc->sc_lo3);
 187        }
 188
 189        used_math = !!used_math();
 190        err |= __put_user(used_math, &sc->sc_used_math);
 191
 192        if (used_math) {
 193                /*
 194                 * Save FPU state to signal context.  Signal handler
 195                 * will "inherit" current FPU state.
 196                 */
 197                err |= protected_save_fp_context32(sc);
 198        }
 199        return err;
 200}
 201
 202static int
 203check_and_restore_fp_context32(struct sigcontext32 __user *sc)
 204{
 205        int err, sig;
 206
 207        err = sig = fpcsr_pending(&sc->sc_fpc_csr);
 208        if (err > 0)
 209                err = 0;
 210        err |= protected_restore_fp_context32(sc);
 211        return err ?: sig;
 212}
 213
 214static int restore_sigcontext32(struct pt_regs *regs,
 215                                struct sigcontext32 __user *sc)
 216{
 217        u32 used_math;
 218        int err = 0;
 219        s32 treg;
 220        int i;
 221
 222        /* Always make any pending restarted system calls return -EINTR */
 223        current_thread_info()->restart_block.fn = do_no_restart_syscall;
 224
 225        err |= __get_user(regs->cp0_epc, &sc->sc_pc);
 226        err |= __get_user(regs->hi, &sc->sc_mdhi);
 227        err |= __get_user(regs->lo, &sc->sc_mdlo);
 228        if (cpu_has_dsp) {
 229                err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
 230                err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
 231                err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
 232                err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
 233                err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
 234                err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
 235                err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
 236        }
 237
 238        for (i = 1; i < 32; i++)
 239                err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
 240
 241        err |= __get_user(used_math, &sc->sc_used_math);
 242        conditional_used_math(used_math);
 243
 244        if (used_math) {
 245                /* restore fpu context if we have used it before */
 246                if (!err)
 247                        err = check_and_restore_fp_context32(sc);
 248        } else {
 249                /* signal handler may have used FPU.  Give it up. */
 250                lose_fpu(0);
 251        }
 252
 253        return err;
 254}
 255
 256/*
 257 *
 258 */
 259extern void __put_sigset_unknown_nsig(void);
 260extern void __get_sigset_unknown_nsig(void);
 261
 262static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t __user *ubuf)
 263{
 264        int err = 0;
 265
 266        if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
 267                return -EFAULT;
 268
 269        switch (_NSIG_WORDS) {
 270        default:
 271                __put_sigset_unknown_nsig();
 272        case 2:
 273                err |= __put_user(kbuf->sig[1] >> 32, &ubuf->sig[3]);
 274                err |= __put_user(kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]);
 275        case 1:
 276                err |= __put_user(kbuf->sig[0] >> 32, &ubuf->sig[1]);
 277                err |= __put_user(kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]);
 278        }
 279
 280        return err;
 281}
 282
 283static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t __user *ubuf)
 284{
 285        int err = 0;
 286        unsigned long sig[4];
 287
 288        if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
 289                return -EFAULT;
 290
 291        switch (_NSIG_WORDS) {
 292        default:
 293                __get_sigset_unknown_nsig();
 294        case 2:
 295                err |= __get_user(sig[3], &ubuf->sig[3]);
 296                err |= __get_user(sig[2], &ubuf->sig[2]);
 297                kbuf->sig[1] = sig[2] | (sig[3] << 32);
 298        case 1:
 299                err |= __get_user(sig[1], &ubuf->sig[1]);
 300                err |= __get_user(sig[0], &ubuf->sig[0]);
 301                kbuf->sig[0] = sig[0] | (sig[1] << 32);
 302        }
 303
 304        return err;
 305}
 306
 307/*
 308 * Atomically swap in the new signal mask, and wait for a signal.
 309 */
 310
 311asmlinkage int sys32_sigsuspend(compat_sigset_t __user *uset)
 312{
 313        return compat_sys_rt_sigsuspend(uset, sizeof(compat_sigset_t));
 314}
 315
 316SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *, act,
 317        struct compat_sigaction __user *, oact)
 318{
 319        struct k_sigaction new_ka, old_ka;
 320        int ret;
 321        int err = 0;
 322
 323        if (act) {
 324                old_sigset_t mask;
 325                s32 handler;
 326
 327                if (!access_ok(VERIFY_READ, act, sizeof(*act)))
 328                        return -EFAULT;
 329                err |= __get_user(handler, &act->sa_handler);
 330                new_ka.sa.sa_handler = (void __user *)(s64)handler;
 331                err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
 332                err |= __get_user(mask, &act->sa_mask.sig[0]);
 333                if (err)
 334                        return -EFAULT;
 335
 336                siginitset(&new_ka.sa.sa_mask, mask);
 337        }
 338
 339        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 340
 341        if (!ret && oact) {
 342                if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
 343                        return -EFAULT;
 344                err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 345                err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
 346                                  &oact->sa_handler);
 347                err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
 348                err |= __put_user(0, &oact->sa_mask.sig[1]);
 349                err |= __put_user(0, &oact->sa_mask.sig[2]);
 350                err |= __put_user(0, &oact->sa_mask.sig[3]);
 351                if (err)
 352                        return -EFAULT;
 353        }
 354
 355        return ret;
 356}
 357
 358int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
 359{
 360        int err;
 361
 362        if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
 363                return -EFAULT;
 364
 365        /* If you change siginfo_t structure, please be sure
 366           this code is fixed accordingly.
 367           It should never copy any pad contained in the structure
 368           to avoid security leaks, but must copy the generic
 369           3 ints plus the relevant union member.
 370           This routine must convert siginfo from 64bit to 32bit as well
 371           at the same time.  */
 372        err = __put_user(from->si_signo, &to->si_signo);
 373        err |= __put_user(from->si_errno, &to->si_errno);
 374        err |= __put_user((short)from->si_code, &to->si_code);
 375        if (from->si_code < 0)
 376                err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
 377        else {
 378                switch (from->si_code >> 16) {
 379                case __SI_TIMER >> 16:
 380                        err |= __put_user(from->si_tid, &to->si_tid);
 381                        err |= __put_user(from->si_overrun, &to->si_overrun);
 382                        err |= __put_user(from->si_int, &to->si_int);
 383                        break;
 384                case __SI_CHLD >> 16:
 385                        err |= __put_user(from->si_utime, &to->si_utime);
 386                        err |= __put_user(from->si_stime, &to->si_stime);
 387                        err |= __put_user(from->si_status, &to->si_status);
 388                default:
 389                        err |= __put_user(from->si_pid, &to->si_pid);
 390                        err |= __put_user(from->si_uid, &to->si_uid);
 391                        break;
 392                case __SI_FAULT >> 16:
 393                        err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
 394                        break;
 395                case __SI_POLL >> 16:
 396                        err |= __put_user(from->si_band, &to->si_band);
 397                        err |= __put_user(from->si_fd, &to->si_fd);
 398                        break;
 399                case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
 400                case __SI_MESGQ >> 16:
 401                        err |= __put_user(from->si_pid, &to->si_pid);
 402                        err |= __put_user(from->si_uid, &to->si_uid);
 403                        err |= __put_user(from->si_int, &to->si_int);
 404                        break;
 405                }
 406        }
 407        return err;
 408}
 409
 410int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
 411{
 412        memset(to, 0, sizeof *to);
 413
 414        if (copy_from_user(to, from, 3*sizeof(int)) ||
 415            copy_from_user(to->_sifields._pad,
 416                           from->_sifields._pad, SI_PAD_SIZE32))
 417                return -EFAULT;
 418
 419        return 0;
 420}
 421
 422asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
 423{
 424        struct sigframe32 __user *frame;
 425        sigset_t blocked;
 426        int sig;
 427
 428        frame = (struct sigframe32 __user *) regs.regs[29];
 429        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 430                goto badframe;
 431        if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
 432                goto badframe;
 433
 434        set_current_blocked(&blocked);
 435
 436        sig = restore_sigcontext32(&regs, &frame->sf_sc);
 437        if (sig < 0)
 438                goto badframe;
 439        else if (sig)
 440                force_sig(sig, current);
 441
 442        /*
 443         * Don't let your children do this ...
 444         */
 445        __asm__ __volatile__(
 446                "move\t$29, %0\n\t"
 447                "j\tsyscall_exit"
 448                :/* no outputs */
 449                :"r" (&regs));
 450        /* Unreached */
 451
 452badframe:
 453        force_sig(SIGSEGV, current);
 454}
 455
 456asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
 457{
 458        struct rt_sigframe32 __user *frame;
 459        sigset_t set;
 460        int sig;
 461
 462        frame = (struct rt_sigframe32 __user *) regs.regs[29];
 463        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 464                goto badframe;
 465        if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
 466                goto badframe;
 467
 468        set_current_blocked(&set);
 469
 470        sig = restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext);
 471        if (sig < 0)
 472                goto badframe;
 473        else if (sig)
 474                force_sig(sig, current);
 475
 476        if (compat_restore_altstack(&frame->rs_uc.uc_stack))
 477                goto badframe;
 478
 479        /*
 480         * Don't let your children do this ...
 481         */
 482        __asm__ __volatile__(
 483                "move\t$29, %0\n\t"
 484                "j\tsyscall_exit"
 485                :/* no outputs */
 486                :"r" (&regs));
 487        /* Unreached */
 488
 489badframe:
 490        force_sig(SIGSEGV, current);
 491}
 492
 493static int setup_frame_32(void *sig_return, struct k_sigaction *ka,
 494                          struct pt_regs *regs, int signr, sigset_t *set)
 495{
 496        struct sigframe32 __user *frame;
 497        int err = 0;
 498
 499        frame = get_sigframe(ka, regs, sizeof(*frame));
 500        if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
 501                goto give_sigsegv;
 502
 503        err |= setup_sigcontext32(regs, &frame->sf_sc);
 504        err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
 505
 506        if (err)
 507                goto give_sigsegv;
 508
 509        /*
 510         * Arguments to signal handler:
 511         *
 512         *   a0 = signal number
 513         *   a1 = 0 (should be cause)
 514         *   a2 = pointer to struct sigcontext
 515         *
 516         * $25 and c0_epc point to the signal handler, $29 points to the
 517         * struct sigframe.
 518         */
 519        regs->regs[ 4] = signr;
 520        regs->regs[ 5] = 0;
 521        regs->regs[ 6] = (unsigned long) &frame->sf_sc;
 522        regs->regs[29] = (unsigned long) frame;
 523        regs->regs[31] = (unsigned long) sig_return;
 524        regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
 525
 526        DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
 527               current->comm, current->pid,
 528               frame, regs->cp0_epc, regs->regs[31]);
 529
 530        return 0;
 531
 532give_sigsegv:
 533        force_sigsegv(signr, current);
 534        return -EFAULT;
 535}
 536
 537static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
 538                             struct pt_regs *regs, int signr, sigset_t *set,
 539                             siginfo_t *info)
 540{
 541        struct rt_sigframe32 __user *frame;
 542        int err = 0;
 543
 544        frame = get_sigframe(ka, regs, sizeof(*frame));
 545        if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
 546                goto give_sigsegv;
 547
 548        /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
 549        err |= copy_siginfo_to_user32(&frame->rs_info, info);
 550
 551        /* Create the ucontext.  */
 552        err |= __put_user(0, &frame->rs_uc.uc_flags);
 553        err |= __put_user(0, &frame->rs_uc.uc_link);
 554        err |= __compat_save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]);
 555        err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
 556        err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
 557
 558        if (err)
 559                goto give_sigsegv;
 560
 561        /*
 562         * Arguments to signal handler:
 563         *
 564         *   a0 = signal number
 565         *   a1 = 0 (should be cause)
 566         *   a2 = pointer to ucontext
 567         *
 568         * $25 and c0_epc point to the signal handler, $29 points to
 569         * the struct rt_sigframe32.
 570         */
 571        regs->regs[ 4] = signr;
 572        regs->regs[ 5] = (unsigned long) &frame->rs_info;
 573        regs->regs[ 6] = (unsigned long) &frame->rs_uc;
 574        regs->regs[29] = (unsigned long) frame;
 575        regs->regs[31] = (unsigned long) sig_return;
 576        regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
 577
 578        DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
 579               current->comm, current->pid,
 580               frame, regs->cp0_epc, regs->regs[31]);
 581
 582        return 0;
 583
 584give_sigsegv:
 585        force_sigsegv(signr, current);
 586        return -EFAULT;
 587}
 588
 589/*
 590 * o32 compatibility on 64-bit kernels, without DSP ASE
 591 */
 592struct mips_abi mips_abi_32 = {
 593        .setup_frame    = setup_frame_32,
 594        .signal_return_offset =
 595                offsetof(struct mips_vdso, o32_signal_trampoline),
 596        .setup_rt_frame = setup_rt_frame_32,
 597        .rt_signal_return_offset =
 598                offsetof(struct mips_vdso, o32_rt_signal_trampoline),
 599        .restart        = __NR_O32_restart_syscall
 600};
 601
 602static int signal32_init(void)
 603{
 604        if (cpu_has_fpu) {
 605                save_fp_context32 = _save_fp_context32;
 606                restore_fp_context32 = _restore_fp_context32;
 607        } else {
 608                save_fp_context32 = copy_fp_to_sigcontext32;
 609                restore_fp_context32 = copy_fp_from_sigcontext32;
 610        }
 611
 612        return 0;
 613}
 614
 615arch_initcall(signal32_init);
 616