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/dsp.h>
  35
  36#include "signal-common.h"
  37
  38/*
  39 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
  40 */
  41#define __NR_O32_restart_syscall        4253
  42
  43/* 32-bit compatibility types */
  44
  45typedef unsigned int __sighandler32_t;
  46typedef void (*vfptr_t)(void);
  47
  48struct ucontext32 {
  49        u32                 uc_flags;
  50        s32                 uc_link;
  51        compat_stack_t      uc_stack;
  52        struct sigcontext32 uc_mcontext;
  53        compat_sigset_t     uc_sigmask;   /* mask last for extensibility */
  54};
  55
  56struct sigframe32 {
  57        u32 sf_ass[4];          /* argument save space for o32 */
  58        u32 sf_pad[2];          /* Was: signal trampoline */
  59        struct sigcontext32 sf_sc;
  60        compat_sigset_t sf_mask;
  61};
  62
  63struct rt_sigframe32 {
  64        u32 rs_ass[4];                  /* argument save space for o32 */
  65        u32 rs_pad[2];                  /* Was: signal trampoline */
  66        compat_siginfo_t rs_info;
  67        struct ucontext32 rs_uc;
  68};
  69
  70static int setup_sigcontext32(struct pt_regs *regs,
  71                              struct sigcontext32 __user *sc)
  72{
  73        int err = 0;
  74        int i;
  75
  76        err |= __put_user(regs->cp0_epc, &sc->sc_pc);
  77
  78        err |= __put_user(0, &sc->sc_regs[0]);
  79        for (i = 1; i < 32; i++)
  80                err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
  81
  82        err |= __put_user(regs->hi, &sc->sc_mdhi);
  83        err |= __put_user(regs->lo, &sc->sc_mdlo);
  84        if (cpu_has_dsp) {
  85                err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
  86                err |= __put_user(mfhi1(), &sc->sc_hi1);
  87                err |= __put_user(mflo1(), &sc->sc_lo1);
  88                err |= __put_user(mfhi2(), &sc->sc_hi2);
  89                err |= __put_user(mflo2(), &sc->sc_lo2);
  90                err |= __put_user(mfhi3(), &sc->sc_hi3);
  91                err |= __put_user(mflo3(), &sc->sc_lo3);
  92        }
  93
  94        /*
  95         * Save FPU state to signal context.  Signal handler
  96         * will "inherit" current FPU state.
  97         */
  98        err |= protected_save_fp_context(sc);
  99
 100        return err;
 101}
 102
 103static int restore_sigcontext32(struct pt_regs *regs,
 104                                struct sigcontext32 __user *sc)
 105{
 106        int err = 0;
 107        s32 treg;
 108        int i;
 109
 110        /* Always make any pending restarted system calls return -EINTR */
 111        current->restart_block.fn = do_no_restart_syscall;
 112
 113        err |= __get_user(regs->cp0_epc, &sc->sc_pc);
 114        err |= __get_user(regs->hi, &sc->sc_mdhi);
 115        err |= __get_user(regs->lo, &sc->sc_mdlo);
 116        if (cpu_has_dsp) {
 117                err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
 118                err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
 119                err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
 120                err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
 121                err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
 122                err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
 123                err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
 124        }
 125
 126        for (i = 1; i < 32; i++)
 127                err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
 128
 129        return err ?: protected_restore_fp_context(sc);
 130}
 131
 132/*
 133 * Atomically swap in the new signal mask, and wait for a signal.
 134 */
 135
 136asmlinkage int sys32_sigsuspend(compat_sigset_t __user *uset)
 137{
 138        return compat_sys_rt_sigsuspend(uset, sizeof(compat_sigset_t));
 139}
 140
 141SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *, act,
 142        struct compat_sigaction __user *, oact)
 143{
 144        struct k_sigaction new_ka, old_ka;
 145        int ret;
 146        int err = 0;
 147
 148        if (act) {
 149                old_sigset_t mask;
 150                s32 handler;
 151
 152                if (!access_ok(VERIFY_READ, act, sizeof(*act)))
 153                        return -EFAULT;
 154                err |= __get_user(handler, &act->sa_handler);
 155                new_ka.sa.sa_handler = (void __user *)(s64)handler;
 156                err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
 157                err |= __get_user(mask, &act->sa_mask.sig[0]);
 158                if (err)
 159                        return -EFAULT;
 160
 161                siginitset(&new_ka.sa.sa_mask, mask);
 162        }
 163
 164        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 165
 166        if (!ret && oact) {
 167                if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
 168                        return -EFAULT;
 169                err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 170                err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
 171                                  &oact->sa_handler);
 172                err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
 173                err |= __put_user(0, &oact->sa_mask.sig[1]);
 174                err |= __put_user(0, &oact->sa_mask.sig[2]);
 175                err |= __put_user(0, &oact->sa_mask.sig[3]);
 176                if (err)
 177                        return -EFAULT;
 178        }
 179
 180        return ret;
 181}
 182
 183int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
 184{
 185        int err;
 186
 187        if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
 188                return -EFAULT;
 189
 190        /* If you change siginfo_t structure, please be sure
 191           this code is fixed accordingly.
 192           It should never copy any pad contained in the structure
 193           to avoid security leaks, but must copy the generic
 194           3 ints plus the relevant union member.
 195           This routine must convert siginfo from 64bit to 32bit as well
 196           at the same time.  */
 197        err = __put_user(from->si_signo, &to->si_signo);
 198        err |= __put_user(from->si_errno, &to->si_errno);
 199        err |= __put_user((short)from->si_code, &to->si_code);
 200        if (from->si_code < 0)
 201                err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
 202        else {
 203                switch (from->si_code >> 16) {
 204                case __SI_TIMER >> 16:
 205                        err |= __put_user(from->si_tid, &to->si_tid);
 206                        err |= __put_user(from->si_overrun, &to->si_overrun);
 207                        err |= __put_user(from->si_int, &to->si_int);
 208                        break;
 209                case __SI_CHLD >> 16:
 210                        err |= __put_user(from->si_utime, &to->si_utime);
 211                        err |= __put_user(from->si_stime, &to->si_stime);
 212                        err |= __put_user(from->si_status, &to->si_status);
 213                default:
 214                        err |= __put_user(from->si_pid, &to->si_pid);
 215                        err |= __put_user(from->si_uid, &to->si_uid);
 216                        break;
 217                case __SI_FAULT >> 16:
 218                        err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
 219                        break;
 220                case __SI_POLL >> 16:
 221                        err |= __put_user(from->si_band, &to->si_band);
 222                        err |= __put_user(from->si_fd, &to->si_fd);
 223                        break;
 224                case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
 225                case __SI_MESGQ >> 16:
 226                        err |= __put_user(from->si_pid, &to->si_pid);
 227                        err |= __put_user(from->si_uid, &to->si_uid);
 228                        err |= __put_user(from->si_int, &to->si_int);
 229                        break;
 230                }
 231        }
 232        return err;
 233}
 234
 235int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
 236{
 237        if (copy_from_user(to, from, 3*sizeof(int)) ||
 238            copy_from_user(to->_sifields._pad,
 239                           from->_sifields._pad, SI_PAD_SIZE32))
 240                return -EFAULT;
 241
 242        return 0;
 243}
 244
 245asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
 246{
 247        struct sigframe32 __user *frame;
 248        sigset_t blocked;
 249        int sig;
 250
 251        frame = (struct sigframe32 __user *) regs.regs[29];
 252        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 253                goto badframe;
 254        if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
 255                goto badframe;
 256
 257        set_current_blocked(&blocked);
 258
 259        sig = restore_sigcontext32(&regs, &frame->sf_sc);
 260        if (sig < 0)
 261                goto badframe;
 262        else if (sig)
 263                force_sig(sig, current);
 264
 265        /*
 266         * Don't let your children do this ...
 267         */
 268        __asm__ __volatile__(
 269                "move\t$29, %0\n\t"
 270                "j\tsyscall_exit"
 271                :/* no outputs */
 272                :"r" (&regs));
 273        /* Unreached */
 274
 275badframe:
 276        force_sig(SIGSEGV, current);
 277}
 278
 279asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
 280{
 281        struct rt_sigframe32 __user *frame;
 282        sigset_t set;
 283        int sig;
 284
 285        frame = (struct rt_sigframe32 __user *) regs.regs[29];
 286        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 287                goto badframe;
 288        if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
 289                goto badframe;
 290
 291        set_current_blocked(&set);
 292
 293        sig = restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext);
 294        if (sig < 0)
 295                goto badframe;
 296        else if (sig)
 297                force_sig(sig, current);
 298
 299        if (compat_restore_altstack(&frame->rs_uc.uc_stack))
 300                goto badframe;
 301
 302        /*
 303         * Don't let your children do this ...
 304         */
 305        __asm__ __volatile__(
 306                "move\t$29, %0\n\t"
 307                "j\tsyscall_exit"
 308                :/* no outputs */
 309                :"r" (&regs));
 310        /* Unreached */
 311
 312badframe:
 313        force_sig(SIGSEGV, current);
 314}
 315
 316static int setup_frame_32(void *sig_return, struct ksignal *ksig,
 317                          struct pt_regs *regs, sigset_t *set)
 318{
 319        struct sigframe32 __user *frame;
 320        int err = 0;
 321
 322        frame = get_sigframe(ksig, regs, sizeof(*frame));
 323        if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
 324                return -EFAULT;
 325
 326        err |= setup_sigcontext32(regs, &frame->sf_sc);
 327        err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
 328
 329        if (err)
 330                return -EFAULT;
 331
 332        /*
 333         * Arguments to signal handler:
 334         *
 335         *   a0 = signal number
 336         *   a1 = 0 (should be cause)
 337         *   a2 = pointer to struct sigcontext
 338         *
 339         * $25 and c0_epc point to the signal handler, $29 points to the
 340         * struct sigframe.
 341         */
 342        regs->regs[ 4] = ksig->sig;
 343        regs->regs[ 5] = 0;
 344        regs->regs[ 6] = (unsigned long) &frame->sf_sc;
 345        regs->regs[29] = (unsigned long) frame;
 346        regs->regs[31] = (unsigned long) sig_return;
 347        regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
 348
 349        DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
 350               current->comm, current->pid,
 351               frame, regs->cp0_epc, regs->regs[31]);
 352
 353        return 0;
 354}
 355
 356static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
 357                             struct pt_regs *regs, sigset_t *set)
 358{
 359        struct rt_sigframe32 __user *frame;
 360        int err = 0;
 361
 362        frame = get_sigframe(ksig, regs, sizeof(*frame));
 363        if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
 364                return -EFAULT;
 365
 366        /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
 367        err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info);
 368
 369        /* Create the ucontext.  */
 370        err |= __put_user(0, &frame->rs_uc.uc_flags);
 371        err |= __put_user(0, &frame->rs_uc.uc_link);
 372        err |= __compat_save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]);
 373        err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
 374        err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
 375
 376        if (err)
 377                return -EFAULT;
 378
 379        /*
 380         * Arguments to signal handler:
 381         *
 382         *   a0 = signal number
 383         *   a1 = 0 (should be cause)
 384         *   a2 = pointer to ucontext
 385         *
 386         * $25 and c0_epc point to the signal handler, $29 points to
 387         * the struct rt_sigframe32.
 388         */
 389        regs->regs[ 4] = ksig->sig;
 390        regs->regs[ 5] = (unsigned long) &frame->rs_info;
 391        regs->regs[ 6] = (unsigned long) &frame->rs_uc;
 392        regs->regs[29] = (unsigned long) frame;
 393        regs->regs[31] = (unsigned long) sig_return;
 394        regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
 395
 396        DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
 397               current->comm, current->pid,
 398               frame, regs->cp0_epc, regs->regs[31]);
 399
 400        return 0;
 401}
 402
 403/*
 404 * o32 compatibility on 64-bit kernels, without DSP ASE
 405 */
 406struct mips_abi mips_abi_32 = {
 407        .setup_frame    = setup_frame_32,
 408        .setup_rt_frame = setup_rt_frame_32,
 409        .restart        = __NR_O32_restart_syscall,
 410
 411        .off_sc_fpregs = offsetof(struct sigcontext32, sc_fpregs),
 412        .off_sc_fpc_csr = offsetof(struct sigcontext32, sc_fpc_csr),
 413        .off_sc_used_math = offsetof(struct sigcontext32, sc_used_math),
 414
 415        .vdso           = &vdso_image_o32,
 416};
 417