linux/arch/x86/um/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
   8#include <linux/personality.h>
   9#include <linux/ptrace.h>
  10#include <linux/kernel.h>
  11#include <asm/unistd.h>
  12#include <asm/uaccess.h>
  13#include <asm/ucontext.h>
  14#include "frame_kern.h"
  15#include "skas.h"
  16
  17#ifdef CONFIG_X86_32
  18
  19/*
  20 * FPU tag word conversions.
  21 */
  22
  23static inline unsigned short twd_i387_to_fxsr(unsigned short twd)
  24{
  25        unsigned int tmp; /* to avoid 16 bit prefixes in the code */
  26
  27        /* Transform each pair of bits into 01 (valid) or 00 (empty) */
  28        tmp = ~twd;
  29        tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
  30        /* and move the valid bits to the lower byte. */
  31        tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
  32        tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
  33        tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
  34        return tmp;
  35}
  36
  37static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave)
  38{
  39        struct _fpxreg *st = NULL;
  40        unsigned long twd = (unsigned long) fxsave->twd;
  41        unsigned long tag;
  42        unsigned long ret = 0xffff0000;
  43        int i;
  44
  45#define FPREG_ADDR(f, n)        ((char *)&(f)->st_space + (n) * 16)
  46
  47        for (i = 0; i < 8; i++) {
  48                if (twd & 0x1) {
  49                        st = (struct _fpxreg *) FPREG_ADDR(fxsave, i);
  50
  51                        switch (st->exponent & 0x7fff) {
  52                        case 0x7fff:
  53                                tag = 2;                /* Special */
  54                                break;
  55                        case 0x0000:
  56                                if ( !st->significand[0] &&
  57                                     !st->significand[1] &&
  58                                     !st->significand[2] &&
  59                                     !st->significand[3] ) {
  60                                        tag = 1;        /* Zero */
  61                                } else {
  62                                        tag = 2;        /* Special */
  63                                }
  64                                break;
  65                        default:
  66                                if (st->significand[3] & 0x8000) {
  67                                        tag = 0;        /* Valid */
  68                                } else {
  69                                        tag = 2;        /* Special */
  70                                }
  71                                break;
  72                        }
  73                } else {
  74                        tag = 3;                        /* Empty */
  75                }
  76                ret |= (tag << (2 * i));
  77                twd = twd >> 1;
  78        }
  79        return ret;
  80}
  81
  82static int convert_fxsr_to_user(struct _fpstate __user *buf,
  83                                struct user_fxsr_struct *fxsave)
  84{
  85        unsigned long env[7];
  86        struct _fpreg __user *to;
  87        struct _fpxreg *from;
  88        int i;
  89
  90        env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul;
  91        env[1] = (unsigned long)fxsave->swd | 0xffff0000ul;
  92        env[2] = twd_fxsr_to_i387(fxsave);
  93        env[3] = fxsave->fip;
  94        env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16);
  95        env[5] = fxsave->foo;
  96        env[6] = fxsave->fos;
  97
  98        if (__copy_to_user(buf, env, 7 * sizeof(unsigned long)))
  99                return 1;
 100
 101        to = &buf->_st[0];
 102        from = (struct _fpxreg *) &fxsave->st_space[0];
 103        for (i = 0; i < 8; i++, to++, from++) {
 104                unsigned long __user *t = (unsigned long __user *)to;
 105                unsigned long *f = (unsigned long *)from;
 106
 107                if (__put_user(*f, t) ||
 108                                __put_user(*(f + 1), t + 1) ||
 109                                __put_user(from->exponent, &to->exponent))
 110                        return 1;
 111        }
 112        return 0;
 113}
 114
 115static int convert_fxsr_from_user(struct user_fxsr_struct *fxsave,
 116                                  struct _fpstate __user *buf)
 117{
 118        unsigned long env[7];
 119        struct _fpxreg *to;
 120        struct _fpreg __user *from;
 121        int i;
 122
 123        if (copy_from_user( env, buf, 7 * sizeof(long)))
 124                return 1;
 125
 126        fxsave->cwd = (unsigned short)(env[0] & 0xffff);
 127        fxsave->swd = (unsigned short)(env[1] & 0xffff);
 128        fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff));
 129        fxsave->fip = env[3];
 130        fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16);
 131        fxsave->fcs = (env[4] & 0xffff);
 132        fxsave->foo = env[5];
 133        fxsave->fos = env[6];
 134
 135        to = (struct _fpxreg *) &fxsave->st_space[0];
 136        from = &buf->_st[0];
 137        for (i = 0; i < 8; i++, to++, from++) {
 138                unsigned long *t = (unsigned long *)to;
 139                unsigned long __user *f = (unsigned long __user *)from;
 140
 141                if (__get_user(*t, f) ||
 142                    __get_user(*(t + 1), f + 1) ||
 143                    __get_user(to->exponent, &from->exponent))
 144                        return 1;
 145        }
 146        return 0;
 147}
 148
 149extern int have_fpx_regs;
 150
 151#endif
 152
 153static int copy_sc_from_user(struct pt_regs *regs,
 154                             struct sigcontext __user *from)
 155{
 156        struct sigcontext sc;
 157        int err, pid;
 158
 159        err = copy_from_user(&sc, from, sizeof(sc));
 160        if (err)
 161                return err;
 162
 163#define GETREG(regno, regname) regs->regs.gp[HOST_##regno] = sc.regname
 164
 165#ifdef CONFIG_X86_32
 166        GETREG(GS, gs);
 167        GETREG(FS, fs);
 168        GETREG(ES, es);
 169        GETREG(DS, ds);
 170#endif
 171        GETREG(DI, di);
 172        GETREG(SI, si);
 173        GETREG(BP, bp);
 174        GETREG(SP, sp);
 175        GETREG(BX, bx);
 176        GETREG(DX, dx);
 177        GETREG(CX, cx);
 178        GETREG(AX, ax);
 179        GETREG(IP, ip);
 180
 181#ifdef CONFIG_X86_64
 182        GETREG(R8, r8);
 183        GETREG(R9, r9);
 184        GETREG(R10, r10);
 185        GETREG(R11, r11);
 186        GETREG(R12, r12);
 187        GETREG(R13, r13);
 188        GETREG(R14, r14);
 189        GETREG(R15, r15);
 190#endif
 191
 192        GETREG(CS, cs);
 193        GETREG(EFLAGS, flags);
 194#ifdef CONFIG_X86_32
 195        GETREG(SS, ss);
 196#endif
 197
 198#undef GETREG
 199
 200        pid = userspace_pid[current_thread_info()->cpu];
 201#ifdef CONFIG_X86_32
 202        if (have_fpx_regs) {
 203                struct user_fxsr_struct fpx;
 204
 205                err = copy_from_user(&fpx,
 206                        &((struct _fpstate __user *)sc.fpstate)->_fxsr_env[0],
 207                                     sizeof(struct user_fxsr_struct));
 208                if (err)
 209                        return 1;
 210
 211                err = convert_fxsr_from_user(&fpx, sc.fpstate);
 212                if (err)
 213                        return 1;
 214
 215                err = restore_fpx_registers(pid, (unsigned long *) &fpx);
 216                if (err < 0) {
 217                        printk(KERN_ERR "copy_sc_from_user - "
 218                               "restore_fpx_registers failed, errno = %d\n",
 219                               -err);
 220                        return 1;
 221                }
 222        } else
 223#endif
 224        {
 225                struct user_i387_struct fp;
 226
 227                err = copy_from_user(&fp, sc.fpstate,
 228                                     sizeof(struct user_i387_struct));
 229                if (err)
 230                        return 1;
 231
 232                err = restore_fp_registers(pid, (unsigned long *) &fp);
 233                if (err < 0) {
 234                        printk(KERN_ERR "copy_sc_from_user - "
 235                               "restore_fp_registers failed, errno = %d\n",
 236                               -err);
 237                        return 1;
 238                }
 239        }
 240        return 0;
 241}
 242
 243static int copy_sc_to_user(struct sigcontext __user *to,
 244                           struct _fpstate __user *to_fp, struct pt_regs *regs,
 245                           unsigned long mask)
 246{
 247        struct sigcontext sc;
 248        struct faultinfo * fi = &current->thread.arch.faultinfo;
 249        int err, pid;
 250        memset(&sc, 0, sizeof(struct sigcontext));
 251
 252#define PUTREG(regno, regname) sc.regname = regs->regs.gp[HOST_##regno]
 253
 254#ifdef CONFIG_X86_32
 255        PUTREG(GS, gs);
 256        PUTREG(FS, fs);
 257        PUTREG(ES, es);
 258        PUTREG(DS, ds);
 259#endif
 260        PUTREG(DI, di);
 261        PUTREG(SI, si);
 262        PUTREG(BP, bp);
 263        PUTREG(SP, sp);
 264        PUTREG(BX, bx);
 265        PUTREG(DX, dx);
 266        PUTREG(CX, cx);
 267        PUTREG(AX, ax);
 268#ifdef CONFIG_X86_64
 269        PUTREG(R8, r8);
 270        PUTREG(R9, r9);
 271        PUTREG(R10, r10);
 272        PUTREG(R11, r11);
 273        PUTREG(R12, r12);
 274        PUTREG(R13, r13);
 275        PUTREG(R14, r14);
 276        PUTREG(R15, r15);
 277#endif
 278
 279        sc.cr2 = fi->cr2;
 280        sc.err = fi->error_code;
 281        sc.trapno = fi->trap_no;
 282        PUTREG(IP, ip);
 283        PUTREG(CS, cs);
 284        PUTREG(EFLAGS, flags);
 285#ifdef CONFIG_X86_32
 286        PUTREG(SP, sp_at_signal);
 287        PUTREG(SS, ss);
 288#endif
 289#undef PUTREG
 290        sc.oldmask = mask;
 291        sc.fpstate = to_fp;
 292
 293        err = copy_to_user(to, &sc, sizeof(struct sigcontext));
 294        if (err)
 295                return 1;
 296
 297        pid = userspace_pid[current_thread_info()->cpu];
 298
 299#ifdef CONFIG_X86_32
 300        if (have_fpx_regs) {
 301                struct user_fxsr_struct fpx;
 302
 303                err = save_fpx_registers(pid, (unsigned long *) &fpx);
 304                if (err < 0){
 305                        printk(KERN_ERR "copy_sc_to_user - save_fpx_registers "
 306                               "failed, errno = %d\n", err);
 307                        return 1;
 308                }
 309
 310                err = convert_fxsr_to_user(to_fp, &fpx);
 311                if (err)
 312                        return 1;
 313
 314                err |= __put_user(fpx.swd, &to_fp->status);
 315                err |= __put_user(X86_FXSR_MAGIC, &to_fp->magic);
 316                if (err)
 317                        return 1;
 318
 319                if (copy_to_user(&to_fp->_fxsr_env[0], &fpx,
 320                                 sizeof(struct user_fxsr_struct)))
 321                        return 1;
 322        } else
 323#endif
 324        {
 325                struct user_i387_struct fp;
 326
 327                err = save_fp_registers(pid, (unsigned long *) &fp);
 328                if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
 329                        return 1;
 330        }
 331
 332        return 0;
 333}
 334
 335#ifdef CONFIG_X86_32
 336static int copy_ucontext_to_user(struct ucontext __user *uc,
 337                                 struct _fpstate __user *fp, sigset_t *set,
 338                                 unsigned long sp)
 339{
 340        int err = 0;
 341
 342        err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp);
 343        err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags);
 344        err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
 345        err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs, 0);
 346        err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
 347        return err;
 348}
 349
 350struct sigframe
 351{
 352        char __user *pretcode;
 353        int sig;
 354        struct sigcontext sc;
 355        struct _fpstate fpstate;
 356        unsigned long extramask[_NSIG_WORDS-1];
 357        char retcode[8];
 358};
 359
 360struct rt_sigframe
 361{
 362        char __user *pretcode;
 363        int sig;
 364        struct siginfo __user *pinfo;
 365        void __user *puc;
 366        struct siginfo info;
 367        struct ucontext uc;
 368        struct _fpstate fpstate;
 369        char retcode[8];
 370};
 371
 372int setup_signal_stack_sc(unsigned long stack_top, int sig,
 373                          struct k_sigaction *ka, struct pt_regs *regs,
 374                          sigset_t *mask)
 375{
 376        struct sigframe __user *frame;
 377        void __user *restorer;
 378        int err = 0;
 379
 380        /* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */
 381        stack_top = ((stack_top + 4) & -16UL) - 4;
 382        frame = (struct sigframe __user *) stack_top - 1;
 383        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 384                return 1;
 385
 386        restorer = frame->retcode;
 387        if (ka->sa.sa_flags & SA_RESTORER)
 388                restorer = ka->sa.sa_restorer;
 389
 390        err |= __put_user(restorer, &frame->pretcode);
 391        err |= __put_user(sig, &frame->sig);
 392        err |= copy_sc_to_user(&frame->sc, &frame->fpstate, regs, mask->sig[0]);
 393        if (_NSIG_WORDS > 1)
 394                err |= __copy_to_user(&frame->extramask, &mask->sig[1],
 395                                      sizeof(frame->extramask));
 396
 397        /*
 398         * This is popl %eax ; movl $,%eax ; int $0x80
 399         *
 400         * WE DO NOT USE IT ANY MORE! It's only left here for historical
 401         * reasons and because gdb uses it as a signature to notice
 402         * signal handler stack frames.
 403         */
 404        err |= __put_user(0xb858, (short __user *)(frame->retcode+0));
 405        err |= __put_user(__NR_sigreturn, (int __user *)(frame->retcode+2));
 406        err |= __put_user(0x80cd, (short __user *)(frame->retcode+6));
 407
 408        if (err)
 409                return err;
 410
 411        PT_REGS_SP(regs) = (unsigned long) frame;
 412        PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
 413        PT_REGS_EAX(regs) = (unsigned long) sig;
 414        PT_REGS_EDX(regs) = (unsigned long) 0;
 415        PT_REGS_ECX(regs) = (unsigned long) 0;
 416
 417        if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
 418                ptrace_notify(SIGTRAP);
 419        return 0;
 420}
 421
 422int setup_signal_stack_si(unsigned long stack_top, int sig,
 423                          struct k_sigaction *ka, struct pt_regs *regs,
 424                          siginfo_t *info, sigset_t *mask)
 425{
 426        struct rt_sigframe __user *frame;
 427        void __user *restorer;
 428        int err = 0;
 429
 430        stack_top &= -8UL;
 431        frame = (struct rt_sigframe __user *) stack_top - 1;
 432        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 433                return 1;
 434
 435        restorer = frame->retcode;
 436        if (ka->sa.sa_flags & SA_RESTORER)
 437                restorer = ka->sa.sa_restorer;
 438
 439        err |= __put_user(restorer, &frame->pretcode);
 440        err |= __put_user(sig, &frame->sig);
 441        err |= __put_user(&frame->info, &frame->pinfo);
 442        err |= __put_user(&frame->uc, &frame->puc);
 443        err |= copy_siginfo_to_user(&frame->info, info);
 444        err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask,
 445                                        PT_REGS_SP(regs));
 446
 447        /*
 448         * This is movl $,%eax ; int $0x80
 449         *
 450         * WE DO NOT USE IT ANY MORE! It's only left here for historical
 451         * reasons and because gdb uses it as a signature to notice
 452         * signal handler stack frames.
 453         */
 454        err |= __put_user(0xb8, (char __user *)(frame->retcode+0));
 455        err |= __put_user(__NR_rt_sigreturn, (int __user *)(frame->retcode+1));
 456        err |= __put_user(0x80cd, (short __user *)(frame->retcode+5));
 457
 458        if (err)
 459                return err;
 460
 461        PT_REGS_SP(regs) = (unsigned long) frame;
 462        PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
 463        PT_REGS_EAX(regs) = (unsigned long) sig;
 464        PT_REGS_EDX(regs) = (unsigned long) &frame->info;
 465        PT_REGS_ECX(regs) = (unsigned long) &frame->uc;
 466
 467        if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
 468                ptrace_notify(SIGTRAP);
 469        return 0;
 470}
 471
 472long sys_sigreturn(struct pt_regs *regs)
 473{
 474        unsigned long sp = PT_REGS_SP(&current->thread.regs);
 475        struct sigframe __user *frame = (struct sigframe __user *)(sp - 8);
 476        sigset_t set;
 477        struct sigcontext __user *sc = &frame->sc;
 478        unsigned long __user *oldmask = &sc->oldmask;
 479        unsigned long __user *extramask = frame->extramask;
 480        int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
 481
 482        if (copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) ||
 483            copy_from_user(&set.sig[1], extramask, sig_size))
 484                goto segfault;
 485
 486        sigdelsetmask(&set, ~_BLOCKABLE);
 487        set_current_blocked(&set);
 488
 489        if (copy_sc_from_user(&current->thread.regs, sc))
 490                goto segfault;
 491
 492        /* Avoid ERESTART handling */
 493        PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
 494        return PT_REGS_SYSCALL_RET(&current->thread.regs);
 495
 496 segfault:
 497        force_sig(SIGSEGV, current);
 498        return 0;
 499}
 500
 501#else
 502
 503struct rt_sigframe
 504{
 505        char __user *pretcode;
 506        struct ucontext uc;
 507        struct siginfo info;
 508        struct _fpstate fpstate;
 509};
 510
 511int setup_signal_stack_si(unsigned long stack_top, int sig,
 512                          struct k_sigaction *ka, struct pt_regs * regs,
 513                          siginfo_t *info, sigset_t *set)
 514{
 515        struct rt_sigframe __user *frame;
 516        int err = 0;
 517        struct task_struct *me = current;
 518
 519        frame = (struct rt_sigframe __user *)
 520                round_down(stack_top - sizeof(struct rt_sigframe), 16);
 521        /* Subtract 128 for a red zone and 8 for proper alignment */
 522        frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8);
 523
 524        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 525                goto out;
 526
 527        if (ka->sa.sa_flags & SA_SIGINFO) {
 528                err |= copy_siginfo_to_user(&frame->info, info);
 529                if (err)
 530                        goto out;
 531        }
 532
 533        /* Create the ucontext.  */
 534        err |= __put_user(0, &frame->uc.uc_flags);
 535        err |= __put_user(0, &frame->uc.uc_link);
 536        err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
 537        err |= __put_user(sas_ss_flags(PT_REGS_SP(regs)),
 538                          &frame->uc.uc_stack.ss_flags);
 539        err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
 540        err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs,
 541                               set->sig[0]);
 542        err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate);
 543        if (sizeof(*set) == 16) {
 544                __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
 545                __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
 546        }
 547        else
 548                err |= __copy_to_user(&frame->uc.uc_sigmask, set,
 549                                      sizeof(*set));
 550
 551        /*
 552         * Set up to return from userspace.  If provided, use a stub
 553         * already in userspace.
 554         */
 555        /* x86-64 should always use SA_RESTORER. */
 556        if (ka->sa.sa_flags & SA_RESTORER)
 557                err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
 558        else
 559                /* could use a vstub here */
 560                return err;
 561
 562        if (err)
 563                return err;
 564
 565        /* Set up registers for signal handler */
 566        {
 567                struct exec_domain *ed = current_thread_info()->exec_domain;
 568                if (unlikely(ed && ed->signal_invmap && sig < 32))
 569                        sig = ed->signal_invmap[sig];
 570        }
 571
 572        PT_REGS_SP(regs) = (unsigned long) frame;
 573        PT_REGS_RDI(regs) = sig;
 574        /* In case the signal handler was declared without prototypes */
 575        PT_REGS_RAX(regs) = 0;
 576
 577        /*
 578         * This also works for non SA_SIGINFO handlers because they expect the
 579         * next argument after the signal number on the stack.
 580         */
 581        PT_REGS_RSI(regs) = (unsigned long) &frame->info;
 582        PT_REGS_RDX(regs) = (unsigned long) &frame->uc;
 583        PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler;
 584 out:
 585        return err;
 586}
 587#endif
 588
 589long sys_rt_sigreturn(struct pt_regs *regs)
 590{
 591        unsigned long sp = PT_REGS_SP(&current->thread.regs);
 592        struct rt_sigframe __user *frame =
 593                (struct rt_sigframe __user *)(sp - sizeof(long));
 594        struct ucontext __user *uc = &frame->uc;
 595        sigset_t set;
 596
 597        if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
 598                goto segfault;
 599
 600        sigdelsetmask(&set, ~_BLOCKABLE);
 601        set_current_blocked(&set);
 602
 603        if (copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext))
 604                goto segfault;
 605
 606        /* Avoid ERESTART handling */
 607        PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
 608        return PT_REGS_SYSCALL_RET(&current->thread.regs);
 609
 610 segfault:
 611        force_sig(SIGSEGV, current);
 612        return 0;
 613}
 614
 615#ifdef CONFIG_X86_32
 616long ptregs_sigreturn(void)
 617{
 618        return sys_sigreturn(NULL);
 619}
 620long ptregs_rt_sigreturn(void)
 621{
 622        return sys_rt_sigreturn(NULL);
 623}
 624#endif
 625
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.