LCOV - code coverage report
Current view: top level - arch/x86/um - signal.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 96 0.0 %
Date: 2023-04-06 08:38:28 Functions: 0 4 0.0 %

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

Generated by: LCOV version 1.14