~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/s390/kernel/compat_signal.c

Version: ~ [ linux-5.12-rc1 ] ~ [ linux-5.11.2 ] ~ [ linux-5.10.19 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.101 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.177 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.222 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.258 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.258 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *    Copyright IBM Corp. 2000, 2006
  3  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  4  *               Gerhard Tonn (ton@de.ibm.com)                  
  5  *
  6  *  Copyright (C) 1991, 1992  Linus Torvalds
  7  *
  8  *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
  9  */
 10 
 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/errno.h>
 18 #include <linux/wait.h>
 19 #include <linux/ptrace.h>
 20 #include <linux/unistd.h>
 21 #include <linux/stddef.h>
 22 #include <linux/tty.h>
 23 #include <linux/personality.h>
 24 #include <linux/binfmts.h>
 25 #include <asm/ucontext.h>
 26 #include <asm/uaccess.h>
 27 #include <asm/lowcore.h>
 28 #include <asm/switch_to.h>
 29 #include "compat_linux.h"
 30 #include "compat_ptrace.h"
 31 #include "entry.h"
 32 
 33 typedef struct 
 34 {
 35         __u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
 36         struct sigcontext32 sc;
 37         _sigregs32 sregs;
 38         int signo;
 39         _sigregs_ext32 sregs_ext;
 40         __u16 svc_insn;         /* Offset of svc_insn is NOT fixed! */
 41 } sigframe32;
 42 
 43 typedef struct 
 44 {
 45         __u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
 46         __u16 svc_insn;
 47         compat_siginfo_t info;
 48         struct ucontext32 uc;
 49 } rt_sigframe32;
 50 
 51 int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
 52 {
 53         int err;
 54 
 55         /* If you change siginfo_t structure, please be sure
 56            this code is fixed accordingly.
 57            It should never copy any pad contained in the structure
 58            to avoid security leaks, but must copy the generic
 59            3 ints plus the relevant union member.  
 60            This routine must convert siginfo from 64bit to 32bit as well
 61            at the same time.  */
 62         err = __put_user(from->si_signo, &to->si_signo);
 63         err |= __put_user(from->si_errno, &to->si_errno);
 64         err |= __put_user((short)from->si_code, &to->si_code);
 65         if (from->si_code < 0)
 66                 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
 67         else {
 68                 switch (from->si_code >> 16) {
 69                 case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
 70                 case __SI_MESGQ >> 16:
 71                         err |= __put_user(from->si_int, &to->si_int);
 72                         /* fallthrough */
 73                 case __SI_KILL >> 16:
 74                         err |= __put_user(from->si_pid, &to->si_pid);
 75                         err |= __put_user(from->si_uid, &to->si_uid);
 76                         break;
 77                 case __SI_CHLD >> 16:
 78                         err |= __put_user(from->si_pid, &to->si_pid);
 79                         err |= __put_user(from->si_uid, &to->si_uid);
 80                         err |= __put_user(from->si_utime, &to->si_utime);
 81                         err |= __put_user(from->si_stime, &to->si_stime);
 82                         err |= __put_user(from->si_status, &to->si_status);
 83                         break;
 84                 case __SI_FAULT >> 16:
 85                         err |= __put_user((unsigned long) from->si_addr,
 86                                           &to->si_addr);
 87                         break;
 88                 case __SI_POLL >> 16:
 89                         err |= __put_user(from->si_band, &to->si_band);
 90                         err |= __put_user(from->si_fd, &to->si_fd);
 91                         break;
 92                 case __SI_TIMER >> 16:
 93                         err |= __put_user(from->si_tid, &to->si_tid);
 94                         err |= __put_user(from->si_overrun, &to->si_overrun);
 95                         err |= __put_user(from->si_int, &to->si_int);
 96                         break;
 97                 default:
 98                         break;
 99                 }
100         }
101         return err ? -EFAULT : 0;
102 }
103 
104 int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
105 {
106         int err;
107         u32 tmp;
108 
109         err = __get_user(to->si_signo, &from->si_signo);
110         err |= __get_user(to->si_errno, &from->si_errno);
111         err |= __get_user(to->si_code, &from->si_code);
112 
113         if (to->si_code < 0)
114                 err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
115         else {
116                 switch (to->si_code >> 16) {
117                 case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
118                 case __SI_MESGQ >> 16:
119                         err |= __get_user(to->si_int, &from->si_int);
120                         /* fallthrough */
121                 case __SI_KILL >> 16:
122                         err |= __get_user(to->si_pid, &from->si_pid);
123                         err |= __get_user(to->si_uid, &from->si_uid);
124                         break;
125                 case __SI_CHLD >> 16:
126                         err |= __get_user(to->si_pid, &from->si_pid);
127                         err |= __get_user(to->si_uid, &from->si_uid);
128                         err |= __get_user(to->si_utime, &from->si_utime);
129                         err |= __get_user(to->si_stime, &from->si_stime);
130                         err |= __get_user(to->si_status, &from->si_status);
131                         break;
132                 case __SI_FAULT >> 16:
133                         err |= __get_user(tmp, &from->si_addr);
134                         to->si_addr = (void __force __user *)
135                                 (u64) (tmp & PSW32_ADDR_INSN);
136                         break;
137                 case __SI_POLL >> 16:
138                         err |= __get_user(to->si_band, &from->si_band);
139                         err |= __get_user(to->si_fd, &from->si_fd);
140                         break;
141                 case __SI_TIMER >> 16:
142                         err |= __get_user(to->si_tid, &from->si_tid);
143                         err |= __get_user(to->si_overrun, &from->si_overrun);
144                         err |= __get_user(to->si_int, &from->si_int);
145                         break;
146                 default:
147                         break;
148                 }
149         }
150         return err ? -EFAULT : 0;
151 }
152 
153 /* Store registers needed to create the signal frame */
154 static void store_sigregs(void)
155 {
156         int i;
157 
158         save_access_regs(current->thread.acrs);
159         save_fp_ctl(&current->thread.fp_regs.fpc);
160         if (current->thread.vxrs) {
161                 save_vx_regs(current->thread.vxrs);
162                 for (i = 0; i < __NUM_FPRS; i++)
163                         current->thread.fp_regs.fprs[i] =
164                                 *(freg_t *)(current->thread.vxrs + i);
165         } else
166                 save_fp_regs(current->thread.fp_regs.fprs);
167 }
168 
169 /* Load registers after signal return */
170 static void load_sigregs(void)
171 {
172         int i;
173 
174         restore_access_regs(current->thread.acrs);
175         /* restore_fp_ctl is done in restore_sigregs */
176         if (current->thread.vxrs) {
177                 for (i = 0; i < __NUM_FPRS; i++)
178                         *(freg_t *)(current->thread.vxrs + i) =
179                                 current->thread.fp_regs.fprs[i];
180                 restore_vx_regs(current->thread.vxrs);
181         } else
182                 restore_fp_regs(current->thread.fp_regs.fprs);
183 }
184 
185 static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
186 {
187         _sigregs32 user_sregs;
188         int i;
189 
190         user_sregs.regs.psw.mask = (__u32)(regs->psw.mask >> 32);
191         user_sregs.regs.psw.mask &= PSW32_MASK_USER | PSW32_MASK_RI;
192         user_sregs.regs.psw.mask |= PSW32_USER_BITS;
193         user_sregs.regs.psw.addr = (__u32) regs->psw.addr |
194                 (__u32)(regs->psw.mask & PSW_MASK_BA);
195         for (i = 0; i < NUM_GPRS; i++)
196                 user_sregs.regs.gprs[i] = (__u32) regs->gprs[i];
197         memcpy(&user_sregs.regs.acrs, current->thread.acrs,
198                sizeof(user_sregs.regs.acrs));
199         memcpy(&user_sregs.fpregs, &current->thread.fp_regs,
200                sizeof(user_sregs.fpregs));
201         if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs32)))
202                 return -EFAULT;
203         return 0;
204 }
205 
206 static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
207 {
208         _sigregs32 user_sregs;
209         int i;
210 
211         /* Alwys make any pending restarted system call return -EINTR */
212         current->restart_block.fn = do_no_restart_syscall;
213 
214         if (__copy_from_user(&user_sregs, &sregs->regs, sizeof(user_sregs)))
215                 return -EFAULT;
216 
217         if (!is_ri_task(current) && (user_sregs.regs.psw.mask & PSW32_MASK_RI))
218                 return -EINVAL;
219 
220         /* Loading the floating-point-control word can fail. Do that first. */
221         if (restore_fp_ctl(&user_sregs.fpregs.fpc))
222                 return -EINVAL;
223 
224         /* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */
225         regs->psw.mask = (regs->psw.mask & ~(PSW_MASK_USER | PSW_MASK_RI)) |
226                 (__u64)(user_sregs.regs.psw.mask & PSW32_MASK_USER) << 32 |
227                 (__u64)(user_sregs.regs.psw.mask & PSW32_MASK_RI) << 32 |
228                 (__u64)(user_sregs.regs.psw.addr & PSW32_ADDR_AMODE);
229         /* Check for invalid user address space control. */
230         if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_HOME)
231                 regs->psw.mask = PSW_ASC_PRIMARY |
232                         (regs->psw.mask & ~PSW_MASK_ASC);
233         regs->psw.addr = (__u64)(user_sregs.regs.psw.addr & PSW32_ADDR_INSN);
234         for (i = 0; i < NUM_GPRS; i++)
235                 regs->gprs[i] = (__u64) user_sregs.regs.gprs[i];
236         memcpy(&current->thread.acrs, &user_sregs.regs.acrs,
237                sizeof(current->thread.acrs));
238 
239         memcpy(&current->thread.fp_regs, &user_sregs.fpregs,
240                sizeof(current->thread.fp_regs));
241 
242         clear_pt_regs_flag(regs, PIF_SYSCALL); /* No longer in a system call */
243         return 0;
244 }
245 
246 static int save_sigregs_ext32(struct pt_regs *regs,
247                               _sigregs_ext32 __user *sregs_ext)
248 {
249         __u32 gprs_high[NUM_GPRS];
250         __u64 vxrs[__NUM_VXRS_LOW];
251         int i;
252 
253         /* Save high gprs to signal stack */
254         for (i = 0; i < NUM_GPRS; i++)
255                 gprs_high[i] = regs->gprs[i] >> 32;
256         if (__copy_to_user(&sregs_ext->gprs_high, &gprs_high,
257                            sizeof(sregs_ext->gprs_high)))
258                 return -EFAULT;
259 
260         /* Save vector registers to signal stack */
261         if (current->thread.vxrs) {
262                 for (i = 0; i < __NUM_VXRS_LOW; i++)
263                         vxrs[i] = *((__u64 *)(current->thread.vxrs + i) + 1);
264                 if (__copy_to_user(&sregs_ext->vxrs_low, vxrs,
265                                    sizeof(sregs_ext->vxrs_low)) ||
266                     __copy_to_user(&sregs_ext->vxrs_high,
267                                    current->thread.vxrs + __NUM_VXRS_LOW,
268                                    sizeof(sregs_ext->vxrs_high)))
269                         return -EFAULT;
270         }
271         return 0;
272 }
273 
274 static int restore_sigregs_ext32(struct pt_regs *regs,
275                                  _sigregs_ext32 __user *sregs_ext)
276 {
277         __u32 gprs_high[NUM_GPRS];
278         __u64 vxrs[__NUM_VXRS_LOW];
279         int i;
280 
281         /* Restore high gprs from signal stack */
282         if (__copy_from_user(&gprs_high, &sregs_ext->gprs_high,
283                              sizeof(&sregs_ext->gprs_high)))
284                 return -EFAULT;
285         for (i = 0; i < NUM_GPRS; i++)
286                 *(__u32 *)&regs->gprs[i] = gprs_high[i];
287 
288         /* Restore vector registers from signal stack */
289         if (current->thread.vxrs) {
290                 if (__copy_from_user(vxrs, &sregs_ext->vxrs_low,
291                                      sizeof(sregs_ext->vxrs_low)) ||
292                     __copy_from_user(current->thread.vxrs + __NUM_VXRS_LOW,
293                                      &sregs_ext->vxrs_high,
294                                      sizeof(sregs_ext->vxrs_high)))
295                         return -EFAULT;
296                 for (i = 0; i < __NUM_VXRS_LOW; i++)
297                         *((__u64 *)(current->thread.vxrs + i) + 1) = vxrs[i];
298         }
299         return 0;
300 }
301 
302 COMPAT_SYSCALL_DEFINE0(sigreturn)
303 {
304         struct pt_regs *regs = task_pt_regs(current);
305         sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15];
306         sigset_t set;
307 
308         if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
309                 goto badframe;
310         set_current_blocked(&set);
311         if (restore_sigregs32(regs, &frame->sregs))
312                 goto badframe;
313         if (restore_sigregs_ext32(regs, &frame->sregs_ext))
314                 goto badframe;
315         load_sigregs();
316         return regs->gprs[2];
317 badframe:
318         force_sig(SIGSEGV, current);
319         return 0;
320 }
321 
322 COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
323 {
324         struct pt_regs *regs = task_pt_regs(current);
325         rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15];
326         sigset_t set;
327 
328         if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
329                 goto badframe;
330         set_current_blocked(&set);
331         if (compat_restore_altstack(&frame->uc.uc_stack))
332                 goto badframe;
333         if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
334                 goto badframe;
335         if (restore_sigregs_ext32(regs, &frame->uc.uc_mcontext_ext))
336                 goto badframe;
337         load_sigregs();
338         return regs->gprs[2];
339 badframe:
340         force_sig(SIGSEGV, current);
341         return 0;
342 }       
343 
344 /*
345  * Set up a signal frame.
346  */
347 
348 
349 /*
350  * Determine which stack to use..
351  */
352 static inline void __user *
353 get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
354 {
355         unsigned long sp;
356 
357         /* Default to using normal stack */
358         sp = (unsigned long) A(regs->gprs[15]);
359 
360         /* Overflow on alternate signal stack gives SIGSEGV. */
361         if (on_sig_stack(sp) && !on_sig_stack((sp - frame_size) & -8UL))
362                 return (void __user *) -1UL;
363 
364         /* This is the X/Open sanctioned signal stack switching.  */
365         if (ka->sa.sa_flags & SA_ONSTACK) {
366                 if (! sas_ss_flags(sp))
367                         sp = current->sas_ss_sp + current->sas_ss_size;
368         }
369 
370         return (void __user *)((sp - frame_size) & -8ul);
371 }
372 
373 static inline int map_signal(int sig)
374 {
375         if (current_thread_info()->exec_domain
376             && current_thread_info()->exec_domain->signal_invmap
377             && sig < 32)
378                 return current_thread_info()->exec_domain->signal_invmap[sig];
379         else
380                 return sig;
381 }
382 
383 static int setup_frame32(struct ksignal *ksig, sigset_t *set,
384                          struct pt_regs *regs)
385 {
386         int sig = ksig->sig;
387         sigframe32 __user *frame;
388         struct sigcontext32 sc;
389         unsigned long restorer;
390         size_t frame_size;
391 
392         /*
393          * gprs_high are always present for 31-bit compat tasks.
394          * The space for vector registers is only allocated if
395          * the machine supports it
396          */
397         frame_size = sizeof(*frame) - sizeof(frame->sregs_ext.__reserved);
398         if (!MACHINE_HAS_VX)
399                 frame_size -= sizeof(frame->sregs_ext.vxrs_low) +
400                               sizeof(frame->sregs_ext.vxrs_high);
401         frame = get_sigframe(&ksig->ka, regs, frame_size);
402         if (frame == (void __user *) -1UL)
403                 return -EFAULT;
404 
405         /* Set up backchain. */
406         if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
407                 return -EFAULT;
408 
409         /* Create struct sigcontext32 on the signal stack */
410         memcpy(&sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32);
411         sc.sregs = (__u32)(unsigned long __force) &frame->sregs;
412         if (__copy_to_user(&frame->sc, &sc, sizeof(frame->sc)))
413                 return -EFAULT;
414 
415         /* Store registers needed to create the signal frame */
416         store_sigregs();
417 
418         /* Create _sigregs32 on the signal stack */
419         if (save_sigregs32(regs, &frame->sregs))
420                 return -EFAULT;
421 
422         /* Place signal number on stack to allow backtrace from handler.  */
423         if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
424                 return -EFAULT;
425 
426         /* Create _sigregs_ext32 on the signal stack */
427         if (save_sigregs_ext32(regs, &frame->sregs_ext))
428                 return -EFAULT;
429 
430         /* Set up to return from userspace.  If provided, use a stub
431            already in userspace.  */
432         if (ksig->ka.sa.sa_flags & SA_RESTORER) {
433                 restorer = (unsigned long __force)
434                         ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE;
435         } else {
436                 /* Signal frames without vectors registers are short ! */
437                 __u16 __user *svc = (void __user *) frame + frame_size - 2;
438                 if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, svc))
439                         return -EFAULT;
440                 restorer = (unsigned long __force) svc | PSW32_ADDR_AMODE;
441         }
442 
443         /* Set up registers for signal handler */
444         regs->gprs[14] = restorer;
445         regs->gprs[15] = (__force __u64) frame;
446         /* Force 31 bit amode and default user address space control. */
447         regs->psw.mask = PSW_MASK_BA |
448                 (PSW_USER_BITS & PSW_MASK_ASC) |
449                 (regs->psw.mask & ~PSW_MASK_ASC);
450         regs->psw.addr = (__force __u64) ksig->ka.sa.sa_handler;
451 
452         regs->gprs[2] = map_signal(sig);
453         regs->gprs[3] = (__force __u64) &frame->sc;
454 
455         /* We forgot to include these in the sigcontext.
456            To avoid breaking binary compatibility, they are passed as args. */
457         if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
458             sig == SIGTRAP || sig == SIGFPE) {
459                 /* set extra registers only for synchronous signals */
460                 regs->gprs[4] = regs->int_code & 127;
461                 regs->gprs[5] = regs->int_parm_long;
462                 regs->gprs[6] = task_thread_info(current)->last_break;
463         }
464 
465         return 0;
466 }
467 
468 static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set,
469                             struct pt_regs *regs)
470 {
471         rt_sigframe32 __user *frame;
472         unsigned long restorer;
473         size_t frame_size;
474         u32 uc_flags;
475 
476         frame_size = sizeof(*frame) -
477                      sizeof(frame->uc.uc_mcontext_ext.__reserved);
478         /*
479          * gprs_high are always present for 31-bit compat tasks.
480          * The space for vector registers is only allocated if
481          * the machine supports it
482          */
483         uc_flags = UC_GPRS_HIGH;
484         if (MACHINE_HAS_VX) {
485                 if (current->thread.vxrs)
486                         uc_flags |= UC_VXRS;
487         } else
488                 frame_size -= sizeof(frame->uc.uc_mcontext_ext.vxrs_low) +
489                               sizeof(frame->uc.uc_mcontext_ext.vxrs_high);
490         frame = get_sigframe(&ksig->ka, regs, frame_size);
491         if (frame == (void __user *) -1UL)
492                 return -EFAULT;
493 
494         /* Set up backchain. */
495         if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame))
496                 return -EFAULT;
497 
498         /* Set up to return from userspace.  If provided, use a stub
499            already in userspace.  */
500         if (ksig->ka.sa.sa_flags & SA_RESTORER) {
501                 restorer = (unsigned long __force)
502                         ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE;
503         } else {
504                 __u16 __user *svc = &frame->svc_insn;
505                 if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, svc))
506                         return -EFAULT;
507                 restorer = (unsigned long __force) svc | PSW32_ADDR_AMODE;
508         }
509 
510         /* Create siginfo on the signal stack */
511         if (copy_siginfo_to_user32(&frame->info, &ksig->info))
512                 return -EFAULT;
513 
514         /* Store registers needed to create the signal frame */
515         store_sigregs();
516 
517         /* Create ucontext on the signal stack. */
518         if (__put_user(uc_flags, &frame->uc.uc_flags) ||
519             __put_user(0, &frame->uc.uc_link) ||
520             __compat_save_altstack(&frame->uc.uc_stack, regs->gprs[15]) ||
521             save_sigregs32(regs, &frame->uc.uc_mcontext) ||
522             __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)) ||
523             save_sigregs_ext32(regs, &frame->uc.uc_mcontext_ext))
524                 return -EFAULT;
525 
526         /* Set up registers for signal handler */
527         regs->gprs[14] = restorer;
528         regs->gprs[15] = (__force __u64) frame;
529         /* Force 31 bit amode and default user address space control. */
530         regs->psw.mask = PSW_MASK_BA |
531                 (PSW_USER_BITS & PSW_MASK_ASC) |
532                 (regs->psw.mask & ~PSW_MASK_ASC);
533         regs->psw.addr = (__u64 __force) ksig->ka.sa.sa_handler;
534 
535         regs->gprs[2] = map_signal(ksig->sig);
536         regs->gprs[3] = (__force __u64) &frame->info;
537         regs->gprs[4] = (__force __u64) &frame->uc;
538         regs->gprs[5] = task_thread_info(current)->last_break;
539         return 0;
540 }
541 
542 /*
543  * OK, we're invoking a handler
544  */     
545 
546 void handle_signal32(struct ksignal *ksig, sigset_t *oldset,
547                      struct pt_regs *regs)
548 {
549         int ret;
550 
551         /* Set up the stack frame */
552         if (ksig->ka.sa.sa_flags & SA_SIGINFO)
553                 ret = setup_rt_frame32(ksig, oldset, regs);
554         else
555                 ret = setup_frame32(ksig, oldset, regs);
556 
557         signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLE_STEP));
558 }
559 
560 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp