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

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

Version: ~ [ linux-5.5-rc1 ] ~ [ linux-5.4.2 ] ~ [ linux-5.3.15 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.88 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.158 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.206 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.206 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.78 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ 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         __u32 gprs_high[NUM_GPRS];
 40         __u8 retcode[S390_SYSCALL_SIZE];
 41 } sigframe32;
 42 
 43 typedef struct 
 44 {
 45         __u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
 46         __u8 retcode[S390_SYSCALL_SIZE];
 47         compat_siginfo_t info;
 48         struct ucontext32 uc;
 49         __u32 gprs_high[NUM_GPRS];
 50 } rt_sigframe32;
 51 
 52 int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
 53 {
 54         int err;
 55 
 56         if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
 57                 return -EFAULT;
 58 
 59         /* If you change siginfo_t structure, please be sure
 60            this code is fixed accordingly.
 61            It should never copy any pad contained in the structure
 62            to avoid security leaks, but must copy the generic
 63            3 ints plus the relevant union member.  
 64            This routine must convert siginfo from 64bit to 32bit as well
 65            at the same time.  */
 66         err = __put_user(from->si_signo, &to->si_signo);
 67         err |= __put_user(from->si_errno, &to->si_errno);
 68         err |= __put_user((short)from->si_code, &to->si_code);
 69         if (from->si_code < 0)
 70                 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
 71         else {
 72                 switch (from->si_code >> 16) {
 73                 case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
 74                 case __SI_MESGQ >> 16:
 75                         err |= __put_user(from->si_int, &to->si_int);
 76                         /* fallthrough */
 77                 case __SI_KILL >> 16:
 78                         err |= __put_user(from->si_pid, &to->si_pid);
 79                         err |= __put_user(from->si_uid, &to->si_uid);
 80                         break;
 81                 case __SI_CHLD >> 16:
 82                         err |= __put_user(from->si_pid, &to->si_pid);
 83                         err |= __put_user(from->si_uid, &to->si_uid);
 84                         err |= __put_user(from->si_utime, &to->si_utime);
 85                         err |= __put_user(from->si_stime, &to->si_stime);
 86                         err |= __put_user(from->si_status, &to->si_status);
 87                         break;
 88                 case __SI_FAULT >> 16:
 89                         err |= __put_user((unsigned long) from->si_addr,
 90                                           &to->si_addr);
 91                         break;
 92                 case __SI_POLL >> 16:
 93                         err |= __put_user(from->si_band, &to->si_band);
 94                         err |= __put_user(from->si_fd, &to->si_fd);
 95                         break;
 96                 case __SI_TIMER >> 16:
 97                         err |= __put_user(from->si_tid, &to->si_tid);
 98                         err |= __put_user(from->si_overrun, &to->si_overrun);
 99                         err |= __put_user(from->si_int, &to->si_int);
100                         break;
101                 default:
102                         break;
103                 }
104         }
105         return err;
106 }
107 
108 int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
109 {
110         int err;
111         u32 tmp;
112 
113         if (!access_ok (VERIFY_READ, from, sizeof(compat_siginfo_t)))
114                 return -EFAULT;
115 
116         err = __get_user(to->si_signo, &from->si_signo);
117         err |= __get_user(to->si_errno, &from->si_errno);
118         err |= __get_user(to->si_code, &from->si_code);
119 
120         if (to->si_code < 0)
121                 err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
122         else {
123                 switch (to->si_code >> 16) {
124                 case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
125                 case __SI_MESGQ >> 16:
126                         err |= __get_user(to->si_int, &from->si_int);
127                         /* fallthrough */
128                 case __SI_KILL >> 16:
129                         err |= __get_user(to->si_pid, &from->si_pid);
130                         err |= __get_user(to->si_uid, &from->si_uid);
131                         break;
132                 case __SI_CHLD >> 16:
133                         err |= __get_user(to->si_pid, &from->si_pid);
134                         err |= __get_user(to->si_uid, &from->si_uid);
135                         err |= __get_user(to->si_utime, &from->si_utime);
136                         err |= __get_user(to->si_stime, &from->si_stime);
137                         err |= __get_user(to->si_status, &from->si_status);
138                         break;
139                 case __SI_FAULT >> 16:
140                         err |= __get_user(tmp, &from->si_addr);
141                         to->si_addr = (void __force __user *)
142                                 (u64) (tmp & PSW32_ADDR_INSN);
143                         break;
144                 case __SI_POLL >> 16:
145                         err |= __get_user(to->si_band, &from->si_band);
146                         err |= __get_user(to->si_fd, &from->si_fd);
147                         break;
148                 case __SI_TIMER >> 16:
149                         err |= __get_user(to->si_tid, &from->si_tid);
150                         err |= __get_user(to->si_overrun, &from->si_overrun);
151                         err |= __get_user(to->si_int, &from->si_int);
152                         break;
153                 default:
154                         break;
155                 }
156         }
157         return err;
158 }
159 
160 asmlinkage long
161 sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
162                  struct old_sigaction32 __user *oact)
163 {
164         struct k_sigaction new_ka, old_ka;
165         unsigned long sa_handler, sa_restorer;
166         int ret;
167 
168         if (act) {
169                 compat_old_sigset_t mask;
170                 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
171                     __get_user(sa_handler, &act->sa_handler) ||
172                     __get_user(sa_restorer, &act->sa_restorer) ||
173                     __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
174                     __get_user(mask, &act->sa_mask))
175                         return -EFAULT;
176                 new_ka.sa.sa_handler = (__sighandler_t) sa_handler;
177                 new_ka.sa.sa_restorer = (void (*)(void)) sa_restorer;
178                 siginitset(&new_ka.sa.sa_mask, mask);
179         }
180 
181         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
182 
183         if (!ret && oact) {
184                 sa_handler = (unsigned long) old_ka.sa.sa_handler;
185                 sa_restorer = (unsigned long) old_ka.sa.sa_restorer;
186                 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
187                     __put_user(sa_handler, &oact->sa_handler) ||
188                     __put_user(sa_restorer, &oact->sa_restorer) ||
189                     __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
190                     __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
191                         return -EFAULT;
192         }
193 
194         return ret;
195 }
196 
197 asmlinkage long
198 sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
199            struct sigaction32 __user *oact,  size_t sigsetsize)
200 {
201         struct k_sigaction new_ka, old_ka;
202         unsigned long sa_handler;
203         int ret;
204         compat_sigset_t set32;
205 
206         /* XXX: Don't preclude handling different sized sigset_t's.  */
207         if (sigsetsize != sizeof(compat_sigset_t))
208                 return -EINVAL;
209 
210         if (act) {
211                 ret = get_user(sa_handler, &act->sa_handler);
212                 ret |= __copy_from_user(&set32, &act->sa_mask,
213                                         sizeof(compat_sigset_t));
214                 new_ka.sa.sa_mask.sig[0] =
215                         set32.sig[0] | (((long)set32.sig[1]) << 32);
216                 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
217                 
218                 if (ret)
219                         return -EFAULT;
220                 new_ka.sa.sa_handler = (__sighandler_t) sa_handler;
221         }
222 
223         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
224 
225         if (!ret && oact) {
226                 set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
227                 set32.sig[0] = old_ka.sa.sa_mask.sig[0];
228                 ret = put_user((unsigned long)old_ka.sa.sa_handler, &oact->sa_handler);
229                 ret |= __copy_to_user(&oact->sa_mask, &set32,
230                                       sizeof(compat_sigset_t));
231                 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
232         }
233 
234         return ret;
235 }
236 
237 asmlinkage long
238 sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss)
239 {
240         struct pt_regs *regs = task_pt_regs(current);
241         stack_t kss, koss;
242         unsigned long ss_sp;
243         int ret, err = 0;
244         mm_segment_t old_fs = get_fs();
245 
246         if (uss) {
247                 if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
248                         return -EFAULT;
249                 err |= __get_user(ss_sp, &uss->ss_sp);
250                 err |= __get_user(kss.ss_size, &uss->ss_size);
251                 err |= __get_user(kss.ss_flags, &uss->ss_flags);
252                 if (err)
253                         return -EFAULT;
254                 kss.ss_sp = (void __user *) ss_sp;
255         }
256 
257         set_fs (KERNEL_DS);
258         ret = do_sigaltstack((stack_t __force __user *) (uss ? &kss : NULL),
259                              (stack_t __force __user *) (uoss ? &koss : NULL),
260                              regs->gprs[15]);
261         set_fs (old_fs);
262 
263         if (!ret && uoss) {
264                 if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
265                         return -EFAULT;
266                 ss_sp = (unsigned long) koss.ss_sp;
267                 err |= __put_user(ss_sp, &uoss->ss_sp);
268                 err |= __put_user(koss.ss_size, &uoss->ss_size);
269                 err |= __put_user(koss.ss_flags, &uoss->ss_flags);
270                 if (err)
271                         return -EFAULT;
272         }
273         return ret;
274 }
275 
276 static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
277 {
278         _s390_regs_common32 regs32;
279         int err, i;
280 
281         regs32.psw.mask = psw32_user_bits |
282                 ((__u32)(regs->psw.mask >> 32) & PSW32_MASK_USER);
283         regs32.psw.addr = (__u32) regs->psw.addr |
284                 (__u32)(regs->psw.mask & PSW_MASK_BA);
285         for (i = 0; i < NUM_GPRS; i++)
286                 regs32.gprs[i] = (__u32) regs->gprs[i];
287         save_access_regs(current->thread.acrs);
288         memcpy(regs32.acrs, current->thread.acrs, sizeof(regs32.acrs));
289         err = __copy_to_user(&sregs->regs, &regs32, sizeof(regs32));
290         if (err)
291                 return err;
292         save_fp_regs(&current->thread.fp_regs);
293         /* s390_fp_regs and _s390_fp_regs32 are the same ! */
294         return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
295                               sizeof(_s390_fp_regs32));
296 }
297 
298 static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
299 {
300         _s390_regs_common32 regs32;
301         int err, i;
302 
303         /* Alwys make any pending restarted system call return -EINTR */
304         current_thread_info()->restart_block.fn = do_no_restart_syscall;
305 
306         err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
307         if (err)
308                 return err;
309         regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
310                 (__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 |
311                 (__u64)(regs32.psw.addr & PSW32_ADDR_AMODE);
312         /* Check for invalid user address space control. */
313         if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
314                 regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
315                         (regs->psw.mask & ~PSW_MASK_ASC);
316         regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
317         for (i = 0; i < NUM_GPRS; i++)
318                 regs->gprs[i] = (__u64) regs32.gprs[i];
319         memcpy(current->thread.acrs, regs32.acrs, sizeof(current->thread.acrs));
320         restore_access_regs(current->thread.acrs);
321 
322         err = __copy_from_user(&current->thread.fp_regs, &sregs->fpregs,
323                                sizeof(_s390_fp_regs32));
324         current->thread.fp_regs.fpc &= FPC_VALID_MASK;
325         if (err)
326                 return err;
327 
328         restore_fp_regs(&current->thread.fp_regs);
329         clear_thread_flag(TIF_SYSCALL); /* No longer in a system call */
330         return 0;
331 }
332 
333 static int save_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
334 {
335         __u32 gprs_high[NUM_GPRS];
336         int i;
337 
338         for (i = 0; i < NUM_GPRS; i++)
339                 gprs_high[i] = regs->gprs[i] >> 32;
340 
341         return __copy_to_user(uregs, &gprs_high, sizeof(gprs_high));
342 }
343 
344 static int restore_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
345 {
346         __u32 gprs_high[NUM_GPRS];
347         int err, i;
348 
349         err = __copy_from_user(&gprs_high, uregs, sizeof(gprs_high));
350         if (err)
351                 return err;
352         for (i = 0; i < NUM_GPRS; i++)
353                 *(__u32 *)&regs->gprs[i] = gprs_high[i];
354         return 0;
355 }
356 
357 asmlinkage long sys32_sigreturn(void)
358 {
359         struct pt_regs *regs = task_pt_regs(current);
360         sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15];
361         sigset_t set;
362 
363         if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
364                 goto badframe;
365         if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
366                 goto badframe;
367         set_current_blocked(&set);
368         if (restore_sigregs32(regs, &frame->sregs))
369                 goto badframe;
370         if (restore_sigregs_gprs_high(regs, frame->gprs_high))
371                 goto badframe;
372         return regs->gprs[2];
373 badframe:
374         force_sig(SIGSEGV, current);
375         return 0;
376 }
377 
378 asmlinkage long sys32_rt_sigreturn(void)
379 {
380         struct pt_regs *regs = task_pt_regs(current);
381         rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15];
382         sigset_t set;
383         stack_t st;
384         __u32 ss_sp;
385         int err;
386         mm_segment_t old_fs = get_fs();
387 
388         if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
389                 goto badframe;
390         if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
391                 goto badframe;
392         set_current_blocked(&set);
393         if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
394                 goto badframe;
395         if (restore_sigregs_gprs_high(regs, frame->gprs_high))
396                 goto badframe;
397         err = __get_user(ss_sp, &frame->uc.uc_stack.ss_sp);
398         st.ss_sp = compat_ptr(ss_sp);
399         err |= __get_user(st.ss_size, &frame->uc.uc_stack.ss_size);
400         err |= __get_user(st.ss_flags, &frame->uc.uc_stack.ss_flags);
401         if (err)
402                 goto badframe; 
403         set_fs (KERNEL_DS);
404         do_sigaltstack((stack_t __force __user *)&st, NULL, regs->gprs[15]);
405         set_fs (old_fs);
406         return regs->gprs[2];
407 badframe:
408         force_sig(SIGSEGV, current);
409         return 0;
410 }       
411 
412 /*
413  * Set up a signal frame.
414  */
415 
416 
417 /*
418  * Determine which stack to use..
419  */
420 static inline void __user *
421 get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
422 {
423         unsigned long sp;
424 
425         /* Default to using normal stack */
426         sp = (unsigned long) A(regs->gprs[15]);
427 
428         /* Overflow on alternate signal stack gives SIGSEGV. */
429         if (on_sig_stack(sp) && !on_sig_stack((sp - frame_size) & -8UL))
430                 return (void __user *) -1UL;
431 
432         /* This is the X/Open sanctioned signal stack switching.  */
433         if (ka->sa.sa_flags & SA_ONSTACK) {
434                 if (! sas_ss_flags(sp))
435                         sp = current->sas_ss_sp + current->sas_ss_size;
436         }
437 
438         return (void __user *)((sp - frame_size) & -8ul);
439 }
440 
441 static inline int map_signal(int sig)
442 {
443         if (current_thread_info()->exec_domain
444             && current_thread_info()->exec_domain->signal_invmap
445             && sig < 32)
446                 return current_thread_info()->exec_domain->signal_invmap[sig];
447         else
448                 return sig;
449 }
450 
451 static int setup_frame32(int sig, struct k_sigaction *ka,
452                         sigset_t *set, struct pt_regs * regs)
453 {
454         sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32));
455         if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe32)))
456                 goto give_sigsegv;
457 
458         if (frame == (void __user *) -1UL)
459                 goto give_sigsegv;
460 
461         if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32))
462                 goto give_sigsegv;
463 
464         if (save_sigregs32(regs, &frame->sregs))
465                 goto give_sigsegv;
466         if (save_sigregs_gprs_high(regs, frame->gprs_high))
467                 goto give_sigsegv;
468         if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs))
469                 goto give_sigsegv;
470 
471         /* Set up to return from userspace.  If provided, use a stub
472            already in userspace.  */
473         if (ka->sa.sa_flags & SA_RESTORER) {
474                 regs->gprs[14] = (__u64) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
475         } else {
476                 regs->gprs[14] = (__u64) frame->retcode | PSW32_ADDR_AMODE;
477                 if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
478                                (u16 __force __user *)(frame->retcode)))
479                         goto give_sigsegv;
480         }
481 
482         /* Set up backchain. */
483         if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
484                 goto give_sigsegv;
485 
486         /* Set up registers for signal handler */
487         regs->gprs[15] = (__force __u64) frame;
488         /* Force 31 bit amode and default user address space control. */
489         regs->psw.mask = PSW_MASK_BA |
490                 (psw_user_bits & PSW_MASK_ASC) |
491                 (regs->psw.mask & ~PSW_MASK_ASC);
492         regs->psw.addr = (__force __u64) ka->sa.sa_handler;
493 
494         regs->gprs[2] = map_signal(sig);
495         regs->gprs[3] = (__force __u64) &frame->sc;
496 
497         /* We forgot to include these in the sigcontext.
498            To avoid breaking binary compatibility, they are passed as args. */
499         if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
500             sig == SIGTRAP || sig == SIGFPE) {
501                 /* set extra registers only for synchronous signals */
502                 regs->gprs[4] = regs->int_code & 127;
503                 regs->gprs[5] = regs->int_parm_long;
504         }
505 
506         /* Place signal number on stack to allow backtrace from handler.  */
507         if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
508                 goto give_sigsegv;
509         return 0;
510 
511 give_sigsegv:
512         force_sigsegv(sig, current);
513         return -EFAULT;
514 }
515 
516 static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
517                            sigset_t *set, struct pt_regs * regs)
518 {
519         int err = 0;
520         rt_sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(rt_sigframe32));
521         if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe32)))
522                 goto give_sigsegv;
523 
524         if (frame == (void __user *) -1UL)
525                 goto give_sigsegv;
526 
527         if (copy_siginfo_to_user32(&frame->info, info))
528                 goto give_sigsegv;
529 
530         /* Create the ucontext.  */
531         err |= __put_user(UC_EXTENDED, &frame->uc.uc_flags);
532         err |= __put_user(0, &frame->uc.uc_link);
533         err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
534         err |= __put_user(sas_ss_flags(regs->gprs[15]),
535                           &frame->uc.uc_stack.ss_flags);
536         err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
537         err |= save_sigregs32(regs, &frame->uc.uc_mcontext);
538         err |= save_sigregs_gprs_high(regs, frame->gprs_high);
539         err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
540         if (err)
541                 goto give_sigsegv;
542 
543         /* Set up to return from userspace.  If provided, use a stub
544            already in userspace.  */
545         if (ka->sa.sa_flags & SA_RESTORER) {
546                 regs->gprs[14] = (__u64) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
547         } else {
548                 regs->gprs[14] = (__u64) frame->retcode | PSW32_ADDR_AMODE;
549                 err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
550                                   (u16 __force __user *)(frame->retcode));
551         }
552 
553         /* Set up backchain. */
554         if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame))
555                 goto give_sigsegv;
556 
557         /* Set up registers for signal handler */
558         regs->gprs[15] = (__force __u64) frame;
559         /* Force 31 bit amode and default user address space control. */
560         regs->psw.mask = PSW_MASK_BA |
561                 (psw_user_bits & PSW_MASK_ASC) |
562                 (regs->psw.mask & ~PSW_MASK_ASC);
563         regs->psw.addr = (__u64) ka->sa.sa_handler;
564 
565         regs->gprs[2] = map_signal(sig);
566         regs->gprs[3] = (__force __u64) &frame->info;
567         regs->gprs[4] = (__force __u64) &frame->uc;
568         return 0;
569 
570 give_sigsegv:
571         force_sigsegv(sig, current);
572         return -EFAULT;
573 }
574 
575 /*
576  * OK, we're invoking a handler
577  */     
578 
579 void handle_signal32(unsigned long sig, struct k_sigaction *ka,
580                     siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
581 {
582         int ret;
583 
584         /* Set up the stack frame */
585         if (ka->sa.sa_flags & SA_SIGINFO)
586                 ret = setup_rt_frame32(sig, ka, info, oldset, regs);
587         else
588                 ret = setup_frame32(sig, ka, oldset, regs);
589         if (ret)
590                 return;
591         signal_delivered(sig, info, ka, regs,
592                                  test_thread_flag(TIF_SINGLE_STEP));
593 }
594 
595 

~ [ 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