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

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

Version: ~ [ linux-5.8 ] ~ [ linux-5.7.12 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.55 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.136 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.191 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.232 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.232 ] ~ [ 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.85 ] ~ [ 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-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  *  arch/s390/kernel/signal32.c
  3  *
  4  *  S390 version
  5  *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  6  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  7  *               Gerhard Tonn (ton@de.ibm.com)                  
  8  *
  9  *  Copyright (C) 1991, 1992  Linus Torvalds
 10  *
 11  *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
 12  */
 13 
 14 #include <linux/config.h>
 15 #include <linux/compat.h>
 16 #include <linux/sched.h>
 17 #include <linux/mm.h>
 18 #include <linux/smp.h>
 19 #include <linux/smp_lock.h>
 20 #include <linux/kernel.h>
 21 #include <linux/signal.h>
 22 #include <linux/errno.h>
 23 #include <linux/wait.h>
 24 #include <linux/ptrace.h>
 25 #include <linux/unistd.h>
 26 #include <linux/stddef.h>
 27 #include <linux/tty.h>
 28 #include <linux/personality.h>
 29 #include <linux/binfmts.h>
 30 #include <asm/ucontext.h>
 31 #include <asm/uaccess.h>
 32 #include <asm/lowcore.h>
 33 #include "compat_linux.h"
 34 #include "compat_ptrace.h"
 35 
 36 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 37 
 38 typedef struct 
 39 {
 40         __u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
 41         struct sigcontext32 sc;
 42         _sigregs32 sregs;
 43         __u8 retcode[S390_SYSCALL_SIZE];
 44 } sigframe32;
 45 
 46 typedef struct 
 47 {
 48         __u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
 49         __u8 retcode[S390_SYSCALL_SIZE];
 50         struct siginfo32 info;
 51         struct ucontext32 uc;
 52 } rt_sigframe32;
 53 
 54 asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
 55 
 56 int do_signal32(struct pt_regs *regs, sigset_t *oldset);
 57 
 58 int copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from)
 59 {
 60         int err;
 61 
 62         if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32)))
 63                 return -EFAULT;
 64 
 65         /* If you change siginfo_t structure, please be sure
 66            this code is fixed accordingly.
 67            It should never copy any pad contained in the structure
 68            to avoid security leaks, but must copy the generic
 69            3 ints plus the relevant union member.  
 70            This routine must convert siginfo from 64bit to 32bit as well
 71            at the same time.  */
 72         err = __put_user(from->si_signo, &to->si_signo);
 73         err |= __put_user(from->si_errno, &to->si_errno);
 74         err |= __put_user((short)from->si_code, &to->si_code);
 75         if (from->si_code < 0)
 76                 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
 77         else {
 78                 switch (from->si_code >> 16) {
 79                 case __SI_KILL >> 16:
 80                         err |= __put_user(from->si_pid, &to->si_pid);
 81                         err |= __put_user(from->si_uid, &to->si_uid);
 82                         break;
 83                 case __SI_CHLD >> 16:
 84                         err |= __put_user(from->si_pid, &to->si_pid);
 85                         err |= __put_user(from->si_uid, &to->si_uid);
 86                         err |= __put_user(from->si_utime, &to->si_utime);
 87                         err |= __put_user(from->si_stime, &to->si_stime);
 88                         err |= __put_user(from->si_status, &to->si_status);
 89                         break;
 90                 case __SI_FAULT >> 16:
 91                         err |= __put_user((unsigned long) from->si_addr,
 92                                           &to->si_addr);
 93                         break;
 94                 case __SI_POLL >> 16:
 95                 case __SI_TIMER >> 16:
 96                         err |= __put_user(from->si_band, &to->si_band);
 97                         err |= __put_user(from->si_fd, &to->si_fd);
 98                         break;
 99                 default:
100                         break;
101                 /* case __SI_RT: This is not generated by the kernel as of now.  */
102                 }
103         }
104         return err;
105 }
106 
107 /*
108  * Atomically swap in the new signal mask, and wait for a signal.
109  */
110 asmlinkage int
111 sys32_sigsuspend(struct pt_regs * regs,int history0, int history1, old_sigset_t mask)
112 {
113         sigset_t saveset;
114 
115         mask &= _BLOCKABLE;
116         spin_lock_irq(&current->sighand->siglock);
117         saveset = current->blocked;
118         siginitset(&current->blocked, mask);
119         recalc_sigpending();
120         spin_unlock_irq(&current->sighand->siglock);
121         regs->gprs[2] = -EINTR;
122 
123         while (1) {
124                 set_current_state(TASK_INTERRUPTIBLE);
125                 schedule();
126                 if (do_signal32(regs, &saveset))
127                         return -EINTR;
128         }
129 }
130 
131 asmlinkage int
132 sys32_rt_sigsuspend(struct pt_regs * regs,compat_sigset_t *unewset, size_t sigsetsize)
133 {
134         sigset_t saveset, newset;
135         compat_sigset_t set32;
136 
137         /* XXX: Don't preclude handling different sized sigset_t's.  */
138         if (sigsetsize != sizeof(sigset_t))
139                 return -EINVAL;
140 
141         if (copy_from_user(&set32, unewset, sizeof(set32)))
142                 return -EFAULT;
143         switch (_NSIG_WORDS) {
144         case 4: newset.sig[3] = set32.sig[6] + (((long)set32.sig[7]) << 32);
145         case 3: newset.sig[2] = set32.sig[4] + (((long)set32.sig[5]) << 32);
146         case 2: newset.sig[1] = set32.sig[2] + (((long)set32.sig[3]) << 32);
147         case 1: newset.sig[0] = set32.sig[0] + (((long)set32.sig[1]) << 32);
148         }
149         sigdelsetmask(&newset, ~_BLOCKABLE);
150 
151         spin_lock_irq(&current->sighand->siglock);
152         saveset = current->blocked;
153         current->blocked = newset;
154         recalc_sigpending();
155         spin_unlock_irq(&current->sighand->siglock);
156         regs->gprs[2] = -EINTR;
157 
158         while (1) {
159                 set_current_state(TASK_INTERRUPTIBLE);
160                 schedule();
161                 if (do_signal32(regs, &saveset))
162                         return -EINTR;
163         }
164 }                                                         
165 
166 asmlinkage int
167 sys32_sigaction(int sig, const struct old_sigaction32 *act,
168                  struct old_sigaction32 *oact)
169 {
170         struct k_sigaction new_ka, old_ka;
171         int ret;
172 
173         if (act) {
174                 compat_old_sigset_t mask;
175                 if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
176                     __get_user((unsigned long)new_ka.sa.sa_handler, &act->sa_handler) ||
177                     __get_user((unsigned long)new_ka.sa.sa_restorer, &act->sa_restorer))
178                         return -EFAULT;
179                 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
180                 __get_user(mask, &act->sa_mask);
181                 siginitset(&new_ka.sa.sa_mask, mask);
182         }
183 
184         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
185 
186         if (!ret && oact) {
187                 if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
188                     __put_user((unsigned long)old_ka.sa.sa_handler, &oact->sa_handler) ||
189                     __put_user((unsigned long)old_ka.sa.sa_restorer, &oact->sa_restorer))
190                         return -EFAULT;
191                 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
192                 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
193         }
194 
195         return ret;
196 }
197 
198 int
199 do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact);
200 
201 asmlinkage long 
202 sys32_rt_sigaction(int sig, const struct sigaction32 *act,
203            struct sigaction32 *oact,  size_t sigsetsize)
204 {
205         struct k_sigaction new_ka, old_ka;
206         int ret;
207         compat_sigset_t set32;
208 
209         /* XXX: Don't preclude handling different sized sigset_t's.  */
210         if (sigsetsize != sizeof(compat_sigset_t))
211                 return -EINVAL;
212 
213         if (act) {
214                 ret = get_user((unsigned long)new_ka.sa.sa_handler, &act->sa_handler);
215                 ret |= __copy_from_user(&set32, &act->sa_mask,
216                                         sizeof(compat_sigset_t));
217                 switch (_NSIG_WORDS) {
218                 case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6]
219                                 | (((long)set32.sig[7]) << 32);
220                 case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4]
221                                 | (((long)set32.sig[5]) << 32);
222                 case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2]
223                                 | (((long)set32.sig[3]) << 32);
224                 case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0]
225                                 | (((long)set32.sig[1]) << 32);
226                 }
227                 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
228                 
229                 if (ret)
230                         return -EFAULT;
231         }
232 
233         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
234 
235         if (!ret && oact) {
236                 switch (_NSIG_WORDS) {
237                 case 4:
238                         set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32);
239                         set32.sig[6] = old_ka.sa.sa_mask.sig[3];
240                 case 3:
241                         set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32);
242                         set32.sig[4] = old_ka.sa.sa_mask.sig[2];
243                 case 2:
244                         set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32);
245                         set32.sig[2] = old_ka.sa.sa_mask.sig[1];
246                 case 1:
247                         set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
248                         set32.sig[0] = old_ka.sa.sa_mask.sig[0];
249                 }
250                 ret = put_user((unsigned long)old_ka.sa.sa_handler, &oact->sa_handler);
251                 ret |= __copy_to_user(&oact->sa_mask, &set32,
252                                       sizeof(compat_sigset_t));
253                 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
254         }
255 
256         return ret;
257 }
258 
259 asmlinkage int
260 sys32_sigaltstack(const stack_t32 *uss, stack_t32 *uoss, struct pt_regs *regs)
261 {
262         stack_t kss, koss;
263         int ret, err = 0;
264         mm_segment_t old_fs = get_fs();
265 
266         if (uss) {
267                 if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
268                         return -EFAULT;
269                 err |= __get_user((unsigned long) kss.ss_sp, &uss->ss_sp);
270                 err |= __get_user(kss.ss_size, &uss->ss_size);
271                 err |= __get_user(kss.ss_flags, &uss->ss_flags);
272                 if (err)
273                         return -EFAULT;
274         }
275 
276         set_fs (KERNEL_DS);
277         ret = do_sigaltstack(uss ? &kss : NULL , uoss ? &koss : NULL, regs->gprs[15]);
278         set_fs (old_fs);
279 
280         if (!ret && uoss) {
281                 if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
282                         return -EFAULT;
283                 err |= __put_user((unsigned long) koss.ss_sp, &uoss->ss_sp);
284                 err |= __put_user(koss.ss_size, &uoss->ss_size);
285                 err |= __put_user(koss.ss_flags, &uoss->ss_flags);
286                 if (err)
287                         return -EFAULT;
288         }
289         return ret;
290 }
291 
292 static int save_sigregs32(struct pt_regs *regs,_sigregs32 *sregs)
293 {
294         _s390_regs_common32 regs32;
295         int err, i;
296 
297         regs32.psw.mask = PSW32_USER_BITS |
298                 ((__u32)(regs->psw.mask >> 32) & PSW32_MASK_CC);
299         regs32.psw.addr = PSW32_ADDR_AMODE31 | (__u32) regs->psw.addr;
300         for (i = 0; i < NUM_GPRS; i++)
301                 regs32.gprs[i] = (__u32) regs->gprs[i];
302         memcpy(regs32.acrs, regs->acrs, sizeof(regs32.acrs));
303         err = __copy_to_user(&sregs->regs, &regs32, sizeof(regs32));
304         if (err)
305                 return err;
306         save_fp_regs(&current->thread.fp_regs);
307         /* s390_fp_regs and _s390_fp_regs32 are the same ! */
308         return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
309                               sizeof(_s390_fp_regs32));
310 }
311 
312 static int restore_sigregs32(struct pt_regs *regs,_sigregs32 *sregs)
313 {
314         _s390_regs_common32 regs32;
315         int err, i;
316 
317         err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
318         if (err)
319                 return err;
320         regs->psw.mask = PSW_USER32_BITS |
321                 (__u64)(regs32.psw.mask & PSW32_MASK_CC) << 32;
322         regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
323         for (i = 0; i < NUM_GPRS; i++)
324                 regs->gprs[i] = (__u64) regs32.gprs[i];
325         memcpy(regs->acrs, regs32.acrs, sizeof(regs32.acrs));
326 
327         err = __copy_from_user(&current->thread.fp_regs, &sregs->fpregs,
328                                sizeof(_s390_fp_regs32));
329         current->thread.fp_regs.fpc &= FPC_VALID_MASK;
330         if (err)
331                 return err;
332 
333         restore_fp_regs(&current->thread.fp_regs);
334         regs->trap = -1;        /* disable syscall checks */
335         return 0;
336 }
337 
338 asmlinkage long sys32_sigreturn(struct pt_regs *regs)
339 {
340         sigframe32 *frame = (sigframe32 *)regs->gprs[15];
341         sigset_t set;
342 
343         if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
344                 goto badframe;
345         if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
346                 goto badframe;
347 
348         sigdelsetmask(&set, ~_BLOCKABLE);
349         spin_lock_irq(&current->sighand->siglock);
350         current->blocked = set;
351         recalc_sigpending();
352         spin_unlock_irq(&current->sighand->siglock);
353 
354         if (restore_sigregs32(regs, &frame->sregs))
355                 goto badframe;
356 
357         return regs->gprs[2];
358 
359 badframe:
360         force_sig(SIGSEGV, current);
361         return 0;
362 }       
363 
364 asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
365 {
366         rt_sigframe32 *frame = (rt_sigframe32 *)regs->gprs[15];
367         sigset_t set;
368         stack_t st;
369         __u32 ss_sp;
370         int err;
371         mm_segment_t old_fs = get_fs();
372 
373         if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
374                 goto badframe;
375         if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
376                 goto badframe;
377 
378         sigdelsetmask(&set, ~_BLOCKABLE);
379         spin_lock_irq(&current->sighand->siglock);
380         current->blocked = set;
381         recalc_sigpending();
382         spin_unlock_irq(&current->sighand->siglock);
383 
384         if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
385                 goto badframe;
386 
387         err = __get_user(ss_sp, &frame->uc.uc_stack.ss_sp);
388         st.ss_sp = (void *) A((unsigned long)ss_sp);
389         err |= __get_user(st.ss_size, &frame->uc.uc_stack.ss_size);
390         err |= __get_user(st.ss_flags, &frame->uc.uc_stack.ss_flags);
391         if (err)
392                 goto badframe; 
393 
394         /* It is more difficult to avoid calling this function than to
395            call it and ignore errors.  */
396         set_fs (KERNEL_DS);   
397         do_sigaltstack(&st, NULL, regs->gprs[15]);
398         set_fs (old_fs);
399 
400         return regs->gprs[2];
401 
402 badframe:
403         force_sig(SIGSEGV, current);
404         return 0;
405 }       
406 
407 /*
408  * Set up a signal frame.
409  */
410 
411 
412 /*
413  * Determine which stack to use..
414  */
415 static inline void *
416 get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
417 {
418         unsigned long sp;
419 
420         /* Default to using normal stack */
421         sp = (unsigned long) A(regs->gprs[15]);
422 
423         /* This is the X/Open sanctioned signal stack switching.  */
424         if (ka->sa.sa_flags & SA_ONSTACK) {
425                 if (! on_sig_stack(sp))
426                         sp = current->sas_ss_sp + current->sas_ss_size;
427         }
428 
429         /* This is the legacy signal stack switching. */
430         else if (!user_mode(regs) &&
431                  !(ka->sa.sa_flags & SA_RESTORER) &&
432                  ka->sa.sa_restorer) {
433                 sp = (unsigned long) ka->sa.sa_restorer;
434         }
435 
436         return (void *)((sp - frame_size) & -8ul);
437 }
438 
439 static inline int map_signal(int sig)
440 {
441         if (current_thread_info()->exec_domain
442             && current_thread_info()->exec_domain->signal_invmap
443             && sig < 32)
444                 return current_thread_info()->exec_domain->signal_invmap[sig];
445         else
446                 return sig;
447 }
448 
449 static void setup_frame32(int sig, struct k_sigaction *ka,
450                         sigset_t *set, struct pt_regs * regs)
451 {
452         sigframe32 *frame = get_sigframe(ka, regs, sizeof(sigframe32));
453         if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe32)))
454                 goto give_sigsegv;
455 
456         if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32))
457                 goto give_sigsegv;
458 
459         if (save_sigregs32(regs, &frame->sregs))
460                 goto give_sigsegv;
461         if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs))
462                 goto give_sigsegv;
463 
464         /* Set up to return from userspace.  If provided, use a stub
465            already in userspace.  */
466         if (ka->sa.sa_flags & SA_RESTORER) {
467                 regs->gprs[14] = (__u64) ka->sa.sa_restorer;
468         } else {
469                 regs->gprs[14] = (__u64) frame->retcode;
470                 if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
471                                (u16 *)(frame->retcode)))
472                         goto give_sigsegv;
473         }
474 
475         /* Set up backchain. */
476         if (__put_user(regs->gprs[15], (unsigned int *) frame))
477                 goto give_sigsegv;
478 
479         /* Set up registers for signal handler */
480         regs->gprs[15] = (__u64) frame;
481         regs->psw.addr = (__u64) ka->sa.sa_handler;
482         regs->psw.mask = PSW_USER32_BITS;
483 
484         regs->gprs[2] = map_signal(sig);
485         regs->gprs[3] = (__u64) &frame->sc;
486 
487         /* We forgot to include these in the sigcontext.
488            To avoid breaking binary compatibility, they are passed as args. */
489         regs->gprs[4] = current->thread.trap_no;
490         regs->gprs[5] = current->thread.prot_addr;
491         return;
492 
493 give_sigsegv:
494         if (sig == SIGSEGV)
495                 ka->sa.sa_handler = SIG_DFL;
496         force_sig(SIGSEGV, current);
497 }
498 
499 static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
500                            sigset_t *set, struct pt_regs * regs)
501 {
502         int err = 0;
503         rt_sigframe32 *frame = get_sigframe(ka, regs, sizeof(rt_sigframe32));
504         if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe32)))
505                 goto give_sigsegv;
506 
507         if (copy_siginfo_to_user32(&frame->info, info))
508                 goto give_sigsegv;
509 
510         /* Create the ucontext.  */
511         err |= __put_user(0, &frame->uc.uc_flags);
512         err |= __put_user(0, &frame->uc.uc_link);
513         err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
514         err |= __put_user(sas_ss_flags(regs->gprs[15]),
515                           &frame->uc.uc_stack.ss_flags);
516         err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
517         err |= save_sigregs32(regs, &frame->uc.uc_mcontext);
518         err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
519         if (err)
520                 goto give_sigsegv;
521 
522         /* Set up to return from userspace.  If provided, use a stub
523            already in userspace.  */
524         if (ka->sa.sa_flags & SA_RESTORER) {
525                 regs->gprs[14] = (__u64) ka->sa.sa_restorer;
526         } else {
527                 regs->gprs[14] = (__u64) frame->retcode;
528                 err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
529                                   (u16 *)(frame->retcode));
530         }
531 
532         /* Set up backchain. */
533         if (__put_user(regs->gprs[15], (unsigned int *) frame))
534                 goto give_sigsegv;
535 
536         /* Set up registers for signal handler */
537         regs->gprs[15] = (__u64) frame;
538         regs->psw.addr = (__u64) ka->sa.sa_handler;
539         regs->psw.mask = PSW_USER32_BITS;
540 
541         regs->gprs[2] = map_signal(sig);
542         regs->gprs[3] = (__u64) &frame->info;
543         regs->gprs[4] = (__u64) &frame->uc;
544         return;
545 
546 give_sigsegv:
547         if (sig == SIGSEGV)
548                 ka->sa.sa_handler = SIG_DFL;
549         force_sig(SIGSEGV, current);
550 }
551 
552 /*
553  * OK, we're invoking a handler
554  */     
555 
556 static void
557 handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset,
558         struct pt_regs * regs)
559 {
560         struct k_sigaction *ka = &current->sighand->action[sig-1];
561 
562         /* Are we from a system call? */
563         if (regs->trap == __LC_SVC_OLD_PSW) {
564                 /* If so, check system call restarting.. */
565                 switch (regs->gprs[2]) {
566                         case -ERESTART_RESTARTBLOCK:
567                                 current_thread_info()->restart_block.fn =
568                                         do_no_restart_syscall;
569                                 clear_thread_flag(TIF_RESTART_SVC);
570                         case -ERESTARTNOHAND:
571                                 regs->gprs[2] = -EINTR;
572                                 break;
573 
574                         case -ERESTARTSYS:
575                                 if (!(ka->sa.sa_flags & SA_RESTART)) {
576                                         regs->gprs[2] = -EINTR;
577                                         break;
578                                 }
579                         /* fallthrough */
580                         case -ERESTARTNOINTR:
581                                 regs->gprs[2] = regs->orig_gpr2;
582                                 regs->psw.addr -= regs->ilc;
583                 }
584         }
585 
586         /* Set up the stack frame */
587         if (ka->sa.sa_flags & SA_SIGINFO)
588                 setup_rt_frame32(sig, ka, info, oldset, regs);
589         else
590                 setup_frame32(sig, ka, oldset, regs);
591 
592         if (ka->sa.sa_flags & SA_ONESHOT)
593                 ka->sa.sa_handler = SIG_DFL;
594 
595         if (!(ka->sa.sa_flags & SA_NODEFER)) {
596                 spin_lock_irq(&current->sighand->siglock);
597                 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
598                 sigaddset(&current->blocked,sig);
599                 recalc_sigpending();
600                 spin_unlock_irq(&current->sighand->siglock);
601         }
602 }
603 
604 /*
605  * Note that 'init' is a special process: it doesn't get signals it doesn't
606  * want to handle. Thus you cannot kill init even with a SIGKILL even by
607  * mistake.
608  *
609  * Note that we go through the signals twice: once to check the signals that
610  * the kernel can handle, and then we build all the user-level signal handling
611  * stack-frames in one go after that.
612  */
613 int do_signal32(struct pt_regs *regs, sigset_t *oldset)
614 {
615         siginfo_t info;
616         int signr;
617 
618         /*
619          * We want the common case to go fast, which
620          * is why we may in certain cases get here from
621          * kernel mode. Just return without doing anything
622          * if so.
623          */
624         if (!user_mode(regs))
625                 return 1;
626 
627         if (!oldset)
628                 oldset = &current->blocked;
629 
630         signr = get_signal_to_deliver(&info, regs, NULL);
631         if (signr > 0) {
632                 /* Whee!  Actually deliver the signal.  */
633                 handle_signal32(signr, &info, oldset, regs);
634                 return 1;
635         }
636 
637         /* Did we come from a system call? */
638         if ( regs->trap == __LC_SVC_OLD_PSW /* System Call! */ ) {
639                 /* Restart the system call - no handlers present */
640                 if (regs->gprs[2] == -ERESTARTNOHAND ||
641                     regs->gprs[2] == -ERESTARTSYS ||
642                     regs->gprs[2] == -ERESTARTNOINTR) {
643                         regs->gprs[2] = regs->orig_gpr2;
644                         regs->psw.addr -= regs->ilc;
645                 }
646                 /* Restart the system call with a new system call number */
647                 if (regs->gprs[2] == -ERESTART_RESTARTBLOCK) {
648                         regs->gprs[2] = __NR_restart_syscall;
649                         set_thread_flag(TIF_RESTART_SVC);
650                 }
651         }
652         return 0;
653 }
654 

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