linux/arch/um/sys-x86_64/signal.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2003 PathScale, Inc.
   3 * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   4 * Licensed under the GPL
   5 */
   6
   7#include <linux/personality.h>
   8#include <linux/ptrace.h>
   9#include <asm/unistd.h>
  10#include <asm/uaccess.h>
  11#include <asm/ucontext.h>
  12#include "frame_kern.h"
  13#include "skas.h"
  14
  15void copy_sc(struct uml_pt_regs *regs, void *from)
  16{
  17        struct sigcontext *sc = from;
  18
  19#define GETREG(regs, regno, sc, regname)                                \
  20        (regs)->gp[(regno) / sizeof(unsigned long)] = (sc)->regname
  21
  22        GETREG(regs, R8, sc, r8);
  23        GETREG(regs, R9, sc, r9);
  24        GETREG(regs, R10, sc, r10);
  25        GETREG(regs, R11, sc, r11);
  26        GETREG(regs, R12, sc, r12);
  27        GETREG(regs, R13, sc, r13);
  28        GETREG(regs, R14, sc, r14);
  29        GETREG(regs, R15, sc, r15);
  30        GETREG(regs, RDI, sc, di);
  31        GETREG(regs, RSI, sc, si);
  32        GETREG(regs, RBP, sc, bp);
  33        GETREG(regs, RBX, sc, bx);
  34        GETREG(regs, RDX, sc, dx);
  35        GETREG(regs, RAX, sc, ax);
  36        GETREG(regs, RCX, sc, cx);
  37        GETREG(regs, RSP, sc, sp);
  38        GETREG(regs, RIP, sc, ip);
  39        GETREG(regs, EFLAGS, sc, flags);
  40        GETREG(regs, CS, sc, cs);
  41
  42#undef GETREG
  43}
  44
  45static int copy_sc_from_user(struct pt_regs *regs,
  46                             struct sigcontext __user *from,
  47                             struct _fpstate __user *fpp)
  48{
  49        struct user_i387_struct fp;
  50        int err = 0;
  51
  52#define GETREG(regs, regno, sc, regname)                                \
  53        __get_user((regs)->regs.gp[(regno) / sizeof(unsigned long)],    \
  54                   &(sc)->regname)
  55
  56        err |= GETREG(regs, R8, from, r8);
  57        err |= GETREG(regs, R9, from, r9);
  58        err |= GETREG(regs, R10, from, r10);
  59        err |= GETREG(regs, R11, from, r11);
  60        err |= GETREG(regs, R12, from, r12);
  61        err |= GETREG(regs, R13, from, r13);
  62        err |= GETREG(regs, R14, from, r14);
  63        err |= GETREG(regs, R15, from, r15);
  64        err |= GETREG(regs, RDI, from, di);
  65        err |= GETREG(regs, RSI, from, si);
  66        err |= GETREG(regs, RBP, from, bp);
  67        err |= GETREG(regs, RBX, from, bx);
  68        err |= GETREG(regs, RDX, from, dx);
  69        err |= GETREG(regs, RAX, from, ax);
  70        err |= GETREG(regs, RCX, from, cx);
  71        err |= GETREG(regs, RSP, from, sp);
  72        err |= GETREG(regs, RIP, from, ip);
  73        err |= GETREG(regs, EFLAGS, from, flags);
  74        err |= GETREG(regs, CS, from, cs);
  75        if (err)
  76                return 1;
  77
  78#undef GETREG
  79
  80        err = copy_from_user(&fp, fpp, sizeof(struct user_i387_struct));
  81        if (err)
  82                return 1;
  83
  84        err = restore_fp_registers(userspace_pid[current_thread_info()->cpu],
  85                                   (unsigned long *) &fp);
  86        if (err < 0) {
  87                printk(KERN_ERR "copy_sc_from_user - "
  88                       "restore_fp_registers failed, errno = %d\n",
  89                       -err);
  90                return 1;
  91        }
  92
  93        return 0;
  94}
  95
  96static int copy_sc_to_user(struct sigcontext __user *to,
  97                           struct _fpstate __user *to_fp, struct pt_regs *regs,
  98                           unsigned long mask, unsigned long sp)
  99{
 100        struct faultinfo * fi = &current->thread.arch.faultinfo;
 101        struct user_i387_struct fp;
 102        int err = 0;
 103
 104        err |= __put_user(0, &to->gs);
 105        err |= __put_user(0, &to->fs);
 106
 107#define PUTREG(regs, regno, sc, regname)                                \
 108        __put_user((regs)->regs.gp[(regno) / sizeof(unsigned long)],    \
 109                   &(sc)->regname)
 110
 111        err |= PUTREG(regs, RDI, to, di);
 112        err |= PUTREG(regs, RSI, to, si);
 113        err |= PUTREG(regs, RBP, to, bp);
 114        /*
 115         * Must use original RSP, which is passed in, rather than what's in
 116         * the pt_regs, because that's already been updated to point at the
 117         * signal frame.
 118         */
 119        err |= __put_user(sp, &to->sp);
 120        err |= PUTREG(regs, RBX, to, bx);
 121        err |= PUTREG(regs, RDX, to, dx);
 122        err |= PUTREG(regs, RCX, to, cx);
 123        err |= PUTREG(regs, RAX, to, ax);
 124        err |= PUTREG(regs, R8, to, r8);
 125        err |= PUTREG(regs, R9, to, r9);
 126        err |= PUTREG(regs, R10, to, r10);
 127        err |= PUTREG(regs, R11, to, r11);
 128        err |= PUTREG(regs, R12, to, r12);
 129        err |= PUTREG(regs, R13, to, r13);
 130        err |= PUTREG(regs, R14, to, r14);
 131        err |= PUTREG(regs, R15, to, r15);
 132        err |= PUTREG(regs, CS, to, cs); /* XXX x86_64 doesn't do this */
 133
 134        err |= __put_user(fi->cr2, &to->cr2);
 135        err |= __put_user(fi->error_code, &to->err);
 136        err |= __put_user(fi->trap_no, &to->trapno);
 137
 138        err |= PUTREG(regs, RIP, to, ip);
 139        err |= PUTREG(regs, EFLAGS, to, flags);
 140#undef PUTREG
 141
 142        err |= __put_user(mask, &to->oldmask);
 143        if (err)
 144                return 1;
 145
 146        err = save_fp_registers(userspace_pid[current_thread_info()->cpu],
 147                                (unsigned long *) &fp);
 148        if (err < 0) {
 149                printk(KERN_ERR "copy_sc_from_user - restore_fp_registers "
 150                       "failed, errno = %d\n", -err);
 151                return 1;
 152        }
 153
 154        if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
 155                return 1;
 156
 157        return err;
 158}
 159
 160struct rt_sigframe
 161{
 162        char __user *pretcode;
 163        struct ucontext uc;
 164        struct siginfo info;
 165        struct _fpstate fpstate;
 166};
 167
 168#define round_down(m, n) (((m) / (n)) * (n))
 169
 170int setup_signal_stack_si(unsigned long stack_top, int sig,
 171                          struct k_sigaction *ka, struct pt_regs * regs,
 172                          siginfo_t *info, sigset_t *set)
 173{
 174        struct rt_sigframe __user *frame;
 175        unsigned long save_sp = PT_REGS_RSP(regs);
 176        int err = 0;
 177        struct task_struct *me = current;
 178
 179        frame = (struct rt_sigframe __user *)
 180                round_down(stack_top - sizeof(struct rt_sigframe), 16);
 181        /* Subtract 128 for a red zone and 8 for proper alignment */
 182        frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8);
 183
 184        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 185                goto out;
 186
 187        if (ka->sa.sa_flags & SA_SIGINFO) {
 188                err |= copy_siginfo_to_user(&frame->info, info);
 189                if (err)
 190                        goto out;
 191        }
 192
 193        /*
 194         * Update SP now because the page fault handler refuses to extend
 195         * the stack if the faulting address is too far below the current
 196         * SP, which frame now certainly is.  If there's an error, the original
 197         * value is restored on the way out.
 198         * When writing the sigcontext to the stack, we have to write the
 199         * original value, so that's passed to copy_sc_to_user, which does
 200         * the right thing with it.
 201         */
 202        PT_REGS_RSP(regs) = (unsigned long) frame;
 203
 204        /* Create the ucontext.  */
 205        err |= __put_user(0, &frame->uc.uc_flags);
 206        err |= __put_user(0, &frame->uc.uc_link);
 207        err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
 208        err |= __put_user(sas_ss_flags(save_sp),
 209                          &frame->uc.uc_stack.ss_flags);
 210        err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
 211        err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs,
 212                               set->sig[0], save_sp);
 213        err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate);
 214        if (sizeof(*set) == 16) {
 215                __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
 216                __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
 217        }
 218        else
 219                err |= __copy_to_user(&frame->uc.uc_sigmask, set,
 220                                      sizeof(*set));
 221
 222        /*
 223         * Set up to return from userspace.  If provided, use a stub
 224         * already in userspace.
 225         */
 226        /* x86-64 should always use SA_RESTORER. */
 227        if (ka->sa.sa_flags & SA_RESTORER)
 228                err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
 229        else
 230                /* could use a vstub here */
 231                goto restore_sp;
 232
 233        if (err)
 234                goto restore_sp;
 235
 236        /* Set up registers for signal handler */
 237        {
 238                struct exec_domain *ed = current_thread_info()->exec_domain;
 239                if (unlikely(ed && ed->signal_invmap && sig < 32))
 240                        sig = ed->signal_invmap[sig];
 241        }
 242
 243        PT_REGS_RDI(regs) = sig;
 244        /* In case the signal handler was declared without prototypes */
 245        PT_REGS_RAX(regs) = 0;
 246
 247        /*
 248         * This also works for non SA_SIGINFO handlers because they expect the
 249         * next argument after the signal number on the stack.
 250         */
 251        PT_REGS_RSI(regs) = (unsigned long) &frame->info;
 252        PT_REGS_RDX(regs) = (unsigned long) &frame->uc;
 253        PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler;
 254 out:
 255        return err;
 256
 257restore_sp:
 258        PT_REGS_RSP(regs) = save_sp;
 259        return err;
 260}
 261
 262long sys_rt_sigreturn(struct pt_regs *regs)
 263{
 264        unsigned long sp = PT_REGS_SP(&current->thread.regs);
 265        struct rt_sigframe __user *frame =
 266                (struct rt_sigframe __user *)(sp - 8);
 267        struct ucontext __user *uc = &frame->uc;
 268        sigset_t set;
 269
 270        if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
 271                goto segfault;
 272
 273        sigdelsetmask(&set, ~_BLOCKABLE);
 274
 275        spin_lock_irq(&current->sighand->siglock);
 276        current->blocked = set;
 277        recalc_sigpending();
 278        spin_unlock_irq(&current->sighand->siglock);
 279
 280        if (copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext,
 281                              &frame->fpstate))
 282                goto segfault;
 283
 284        /* Avoid ERESTART handling */
 285        PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
 286        return PT_REGS_SYSCALL_RET(&current->thread.regs);
 287
 288 segfault:
 289        force_sig(SIGSEGV, current);
 290        return 0;
 291}
 292