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

TOMOYO Linux Cross Reference
Linux/arch/sh/kernel/signal.c

Version: ~ [ linux-5.19-rc3 ] ~ [ linux-5.18.5 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.48 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.123 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.199 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.248 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.284 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.319 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.302 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ 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.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* $Id: signal.c,v 1.1.1.1.2.12 2003/10/01 10:54:28 kkojima Exp $
  2  *
  3  *  linux/arch/sh/kernel/signal.c
  4  *
  5  *  Copyright (C) 1991, 1992  Linus Torvalds
  6  *
  7  *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
  8  *
  9  *  SuperH version:  Copyright (C) 1999, 2000  Niibe Yutaka & Kaz Kojima
 10  *
 11  */
 12 
 13 #include <linux/sched.h>
 14 #include <linux/mm.h>
 15 #include <linux/smp.h>
 16 #include <linux/smp_lock.h>
 17 #include <linux/kernel.h>
 18 #include <linux/signal.h>
 19 #include <linux/errno.h>
 20 #include <linux/wait.h>
 21 #include <linux/ptrace.h>
 22 #include <linux/unistd.h>
 23 #include <linux/stddef.h>
 24 #include <linux/personality.h>
 25 #include <asm/ucontext.h>
 26 #include <asm/uaccess.h>
 27 #include <asm/pgtable.h>
 28 
 29 #define DEBUG_SIG 0
 30 
 31 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 32 
 33 asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset,
 34                          int from_syscall, unsigned long orig_r0);
 35 
 36 int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
 37 {
 38         if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
 39                 return -EFAULT;
 40         if (from->si_code < 0)
 41                 return __copy_to_user(to, from, sizeof(siginfo_t));
 42         else {
 43                 int err;
 44 
 45                 /* If you change siginfo_t structure, please be sure
 46                    this code is fixed accordingly.
 47                    It should never copy any pad contained in the structure
 48                    to avoid security leaks, but must copy the generic
 49                    3 ints plus the relevant union member.  */
 50                 err = __put_user(from->si_signo, &to->si_signo);
 51                 err |= __put_user(from->si_errno, &to->si_errno);
 52                 err |= __put_user((short)from->si_code, &to->si_code);
 53                 /* First 32bits of unions are always present.  */
 54                 err |= __put_user(from->si_pid, &to->si_pid);
 55                 switch (from->si_code >> 16) {
 56                 case __SI_FAULT >> 16:
 57                         break;
 58                 case __SI_CHLD >> 16:
 59                         err |= __put_user(from->si_utime, &to->si_utime);
 60                         err |= __put_user(from->si_stime, &to->si_stime);
 61                         err |= __put_user(from->si_status, &to->si_status);
 62                 default:
 63                         err |= __put_user(from->si_uid, &to->si_uid);
 64                         break;
 65                 /* case __SI_RT: This is not generated by the kernel as of now.  */
 66                 }
 67                 return err;
 68         }
 69 }
 70 
 71 /*
 72  * Atomically swap in the new signal mask, and wait for a signal.
 73  */
 74 asmlinkage int
 75 sys_sigsuspend(old_sigset_t mask,
 76                unsigned long r5, unsigned long r6, unsigned long r7,
 77                struct pt_regs regs)
 78 {
 79         sigset_t saveset;
 80 
 81         mask &= _BLOCKABLE;
 82         spin_lock_irq(&current->sigmask_lock);
 83         saveset = current->blocked;
 84         siginitset(&current->blocked, mask);
 85         recalc_sigpending(current);
 86         spin_unlock_irq(&current->sigmask_lock);
 87 
 88         regs.regs[0] = -EINTR;
 89         while (1) {
 90                 current->state = TASK_INTERRUPTIBLE;
 91                 schedule();
 92                 if (do_signal(&regs, &saveset, 0, 0))
 93                         return -EINTR;
 94         }
 95 }
 96 
 97 asmlinkage int
 98 sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
 99                   unsigned long r6, unsigned long r7,
100                   struct pt_regs regs)
101 {
102         sigset_t saveset, newset;
103 
104         /* XXX: Don't preclude handling different sized sigset_t's.  */
105         if (sigsetsize != sizeof(sigset_t))
106                 return -EINVAL;
107 
108         if (copy_from_user(&newset, unewset, sizeof(newset)))
109                 return -EFAULT;
110         sigdelsetmask(&newset, ~_BLOCKABLE);
111         spin_lock_irq(&current->sigmask_lock);
112         saveset = current->blocked;
113         current->blocked = newset;
114         recalc_sigpending(current);
115         spin_unlock_irq(&current->sigmask_lock);
116 
117         regs.regs[0] = -EINTR;
118         while (1) {
119                 current->state = TASK_INTERRUPTIBLE;
120                 schedule();
121                 if (do_signal(&regs, &saveset, 0, 0))
122                         return -EINTR;
123         }
124 }
125 
126 asmlinkage int 
127 sys_sigaction(int sig, const struct old_sigaction *act,
128               struct old_sigaction *oact)
129 {
130         struct k_sigaction new_ka, old_ka;
131         int ret;
132 
133         if (act) {
134                 old_sigset_t mask;
135                 if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
136                     __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
137                     __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
138                         return -EFAULT;
139                 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
140                 __get_user(mask, &act->sa_mask);
141                 siginitset(&new_ka.sa.sa_mask, mask);
142         }
143 
144         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
145 
146         if (!ret && oact) {
147                 if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
148                     __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
149                     __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
150                         return -EFAULT;
151                 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
152                 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
153         }
154 
155         return ret;
156 }
157 
158 asmlinkage int
159 sys_sigaltstack(const stack_t *uss, stack_t *uoss,
160                 unsigned long r6, unsigned long r7,
161                 struct pt_regs regs)
162 {
163         return do_sigaltstack(uss, uoss, regs.regs[15]);
164 }
165 
166 
167 /*
168  * Do a signal return; undo the signal stack.
169  */
170 
171 #define MOVW(n)  (0x9300|((n)-2))       /* Move mem word at PC+n to R3 */
172 #define TRAP16   0xc310                 /* Syscall w/no args (NR in R3) */
173 #define OR_R0_R0 0x200b                 /* or r0,r0 (insert to avoid hardware bug) */
174 
175 struct sigframe
176 {
177         struct sigcontext sc;
178         unsigned long extramask[_NSIG_WORDS-1];
179         u16 retcode[8];
180 };
181 
182 struct rt_sigframe
183 {
184         struct siginfo info;
185         struct ucontext uc;
186         u16 retcode[8];
187 };
188 
189 #if defined(__SH4__)
190 static inline int restore_sigcontext_fpu(struct sigcontext *sc)
191 {
192         struct task_struct *tsk = current;
193 
194         tsk->used_math = 1;
195         return __copy_from_user(&tsk->thread.fpu.hard, &sc->sc_fpregs[0],
196                                 sizeof(long)*(16*2+2));
197 }
198 
199 static inline int save_sigcontext_fpu(struct sigcontext *sc)
200 {
201         struct task_struct *tsk = current;
202 
203         if (!tsk->used_math) {
204                 __put_user(0, &sc->sc_ownedfp);
205                 return 0;
206         }
207 
208         __put_user(1, &sc->sc_ownedfp);
209 
210         /* This will cause a "finit" to be triggered by the next
211            attempted FPU operation by the 'current' process.
212            */
213         tsk->used_math = 0;
214 
215         unlazy_fpu(tsk);
216         return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard,
217                               sizeof(long)*(16*2+2));
218 }
219 #endif
220 
221 static int
222 restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
223 {
224         unsigned int err = 0;
225 
226 #define COPY(x)         err |= __get_user(regs->x, &sc->sc_##x)
227         COPY(regs[0]);  COPY(regs[1]);
228         COPY(regs[2]);  COPY(regs[3]);
229         COPY(regs[4]);  COPY(regs[5]);
230         COPY(regs[6]);  COPY(regs[7]);
231         COPY(regs[8]);  COPY(regs[9]);
232         COPY(regs[10]); COPY(regs[11]);
233         COPY(regs[12]); COPY(regs[13]);
234         COPY(regs[14]); COPY(regs[15]);
235         COPY(gbr);      COPY(mach);
236         COPY(macl);     COPY(pr);
237         COPY(sr);       COPY(pc);
238 #undef COPY
239 
240 #if defined(__SH4__)
241         {
242                 int owned_fp;
243                 struct task_struct *tsk = current;
244 
245                 regs->sr |= SR_FD; /* Release FPU */
246                 clear_fpu(tsk);
247                 current->used_math = 0;
248                 __get_user (owned_fp, &sc->sc_ownedfp);
249                 if (owned_fp)
250                         err |= restore_sigcontext_fpu(sc);
251         }
252 #endif
253         return err;
254 }
255 
256 
257 asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
258                              unsigned long r6, unsigned long r7,
259                              struct pt_regs regs)
260 {
261         struct sigframe *frame = (struct sigframe *)regs.regs[15];
262         sigset_t set;
263 
264         if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
265                 goto badframe;
266 
267         if (__get_user(set.sig[0], &frame->sc.oldmask)
268             || (_NSIG_WORDS > 1
269                 && __copy_from_user(&set.sig[1], &frame->extramask,
270                                     sizeof(frame->extramask))))
271                 goto badframe;
272 
273         sigdelsetmask(&set, ~_BLOCKABLE);
274 
275         spin_lock_irq(&current->sigmask_lock);
276         current->blocked = set;
277         recalc_sigpending(current);
278         spin_unlock_irq(&current->sigmask_lock);
279 
280         if (restore_sigcontext(&regs, &frame->sc))
281                 goto badframe;
282         return regs.regs[0];
283 
284 badframe:
285         force_sig(SIGSEGV, current);
286         return 0;
287 }
288 
289 asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
290                                 unsigned long r6, unsigned long r7,
291                                 struct pt_regs regs)
292 {
293         struct rt_sigframe *frame = (struct rt_sigframe *)regs.regs[15];
294         sigset_t set;
295         stack_t st;
296 
297         if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
298                 goto badframe;
299 
300         if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
301                 goto badframe;
302 
303         sigdelsetmask(&set, ~_BLOCKABLE);
304         spin_lock_irq(&current->sigmask_lock);
305         current->blocked = set;
306         recalc_sigpending(current);
307         spin_unlock_irq(&current->sigmask_lock);
308 
309         if (restore_sigcontext(&regs, &frame->uc.uc_mcontext))
310                 goto badframe;
311 
312         if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
313                 goto badframe;
314         /* It is more difficult to avoid calling this function than to
315            call it and ignore errors.  */
316         do_sigaltstack(&st, NULL, regs.regs[15]);
317         return regs.regs[0];
318 
319 badframe:
320         force_sig(SIGSEGV, current);
321         return 0;
322 }
323 
324 /*
325  * Set up a signal frame.
326  */
327 
328 static int
329 setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
330                  unsigned long mask)
331 {
332         int err = 0;
333 
334 #define COPY(x)         err |= __put_user(regs->x, &sc->sc_##x)
335         COPY(regs[0]);  COPY(regs[1]);
336         COPY(regs[2]);  COPY(regs[3]);
337         COPY(regs[4]);  COPY(regs[5]);
338         COPY(regs[6]);  COPY(regs[7]);
339         COPY(regs[8]);  COPY(regs[9]);
340         COPY(regs[10]); COPY(regs[11]);
341         COPY(regs[12]); COPY(regs[13]);
342         COPY(regs[14]); COPY(regs[15]);
343         COPY(gbr);      COPY(mach);
344         COPY(macl);     COPY(pr);
345         COPY(sr);       COPY(pc);
346 #undef COPY
347 
348 #if defined(__SH4__)
349         err |= save_sigcontext_fpu(sc);
350 #endif
351 
352         /* non-iBCS2 extensions.. */
353         err |= __put_user(mask, &sc->oldmask);
354 
355         return err;
356 }
357 
358 /*
359  * Determine which stack to use..
360  */
361 static inline void *
362 get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
363 {
364         if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
365                 sp = current->sas_ss_sp + current->sas_ss_size;
366 
367         return (void *)((sp - frame_size) & -8ul);
368 }
369 
370 static void setup_frame(int sig, struct k_sigaction *ka,
371                         sigset_t *set, struct pt_regs *regs)
372 {
373         struct sigframe *frame;
374         int err = 0;
375         int signal;
376 
377         frame = get_sigframe(ka, regs->regs[15], sizeof(*frame));
378 
379         if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
380                 goto give_sigsegv;
381 
382         signal = current->exec_domain
383                 && current->exec_domain->signal_invmap
384                 && sig < 32
385                 ? current->exec_domain->signal_invmap[sig]
386                 : sig;
387 
388         err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
389 
390         if (_NSIG_WORDS > 1) {
391                 err |= __copy_to_user(frame->extramask, &set->sig[1],
392                                       sizeof(frame->extramask));
393         }
394 
395         /* Set up to return from userspace.  If provided, use a stub
396            already in userspace.  */
397         if (ka->sa.sa_flags & SA_RESTORER) {
398                 regs->pr = (unsigned long) ka->sa.sa_restorer;
399         } else {
400                 /* Generate return code (system call to sigreturn) */
401                 err |= __put_user(MOVW(7), &frame->retcode[0]);
402                 err |= __put_user(TRAP16, &frame->retcode[1]);
403                 err |= __put_user(OR_R0_R0, &frame->retcode[2]);
404                 err |= __put_user(OR_R0_R0, &frame->retcode[3]);
405                 err |= __put_user(OR_R0_R0, &frame->retcode[4]);
406                 err |= __put_user(OR_R0_R0, &frame->retcode[5]);
407                 err |= __put_user(OR_R0_R0, &frame->retcode[6]);
408                 err |= __put_user((__NR_sigreturn), &frame->retcode[7]);
409                 regs->pr = (unsigned long) frame->retcode;
410         }
411 
412         if (err)
413                 goto give_sigsegv;
414 
415         /* Set up registers for signal handler */
416         regs->regs[15] = (unsigned long) frame;
417         regs->regs[4] = signal; /* Arg for signal handler */
418         regs->regs[5] = 0;
419         regs->regs[6] = (unsigned long) &frame->sc;
420         regs->pc = (unsigned long) ka->sa.sa_handler;
421 
422         set_fs(USER_DS);
423 
424 #if DEBUG_SIG
425         printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
426                 current->comm, current->pid, frame, regs->pc, regs->pr);
427 #endif
428 
429         flush_cache_sigtramp(regs->pr);
430         if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
431                 flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
432         return;
433 
434 give_sigsegv:
435         if (sig == SIGSEGV)
436                 ka->sa.sa_handler = SIG_DFL;
437         force_sig(SIGSEGV, current);
438 }
439 
440 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
441                            sigset_t *set, struct pt_regs *regs)
442 {
443         struct rt_sigframe *frame;
444         int err = 0;
445         int signal;
446 
447         frame = get_sigframe(ka, regs->regs[15], sizeof(*frame));
448 
449         if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
450                 goto give_sigsegv;
451 
452         signal = current->exec_domain
453                 && current->exec_domain->signal_invmap
454                 && sig < 32
455                 ? current->exec_domain->signal_invmap[sig]
456                 : sig;
457 
458         err |= copy_siginfo_to_user(&frame->info, info);
459 
460         /* Create the ucontext.  */
461         err |= __put_user(0, &frame->uc.uc_flags);
462         err |= __put_user(0, &frame->uc.uc_link);
463         err |= __put_user((void *)current->sas_ss_sp,
464                           &frame->uc.uc_stack.ss_sp);
465         err |= __put_user(sas_ss_flags(regs->regs[15]),
466                           &frame->uc.uc_stack.ss_flags);
467         err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
468         err |= setup_sigcontext(&frame->uc.uc_mcontext,
469                                 regs, set->sig[0]);
470         err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
471 
472         /* Set up to return from userspace.  If provided, use a stub
473            already in userspace.  */
474         if (ka->sa.sa_flags & SA_RESTORER) {
475                 regs->pr = (unsigned long) ka->sa.sa_restorer;
476         } else {
477                 /* Generate return code (system call to rt_sigreturn) */
478                 err |= __put_user(MOVW(7), &frame->retcode[0]);
479                 err |= __put_user(TRAP16, &frame->retcode[1]);
480                 err |= __put_user(OR_R0_R0, &frame->retcode[2]);
481                 err |= __put_user(OR_R0_R0, &frame->retcode[3]);
482                 err |= __put_user(OR_R0_R0, &frame->retcode[4]);
483                 err |= __put_user(OR_R0_R0, &frame->retcode[5]);
484                 err |= __put_user(OR_R0_R0, &frame->retcode[6]);
485                 err |= __put_user((__NR_rt_sigreturn), &frame->retcode[7]);
486                 regs->pr = (unsigned long) frame->retcode;
487         }
488 
489         if (err)
490                 goto give_sigsegv;
491 
492         /* Set up registers (SP, PC, and args) for signal handler */
493         regs->regs[15] = (unsigned long) frame;         /* Stack pointer */
494         regs->regs[4] = signal;                         /* Arg1 (signal) */
495         regs->regs[5] = (unsigned long)&frame->info;    /* Arg2 (siginfo) */
496         regs->regs[6] = (unsigned long)&frame->uc;      /* Arg3 (context) */
497         regs->pc = (unsigned long) ka->sa.sa_handler;   /* Program counter */
498 
499         set_fs(USER_DS);
500 
501 #if DEBUG_SIG
502         printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
503                 current->comm, current->pid, frame, regs->pc, regs->pr);
504 #endif
505 
506         flush_cache_sigtramp(regs->pr);
507         if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
508                 flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
509         return;
510 
511 give_sigsegv:
512         if (sig == SIGSEGV)
513                 ka->sa.sa_handler = SIG_DFL;
514         force_sig(SIGSEGV, current);
515 }
516 
517 /*
518  * OK, we're invoking a handler
519  */     
520 
521 static void
522 handle_signal(unsigned long sig, struct k_sigaction *ka,
523               siginfo_t *info, sigset_t *oldset, struct pt_regs *regs, 
524               int from_syscall, unsigned long orig_r0)
525 {
526         /* Are we from a system call? */
527         if (from_syscall) {
528                 /* If so, check system call restarting.. */
529                 switch (regs->regs[0]) {
530                         case -ERESTARTNOHAND:
531                                 regs->regs[0] = -EINTR;
532                                 break;
533 
534                         case -ERESTARTSYS:
535                                 if (!(ka->sa.sa_flags & SA_RESTART)) {
536                                         regs->regs[0] = -EINTR;
537                                         break;
538                                 }
539                         /* fallthrough */
540                         case -ERESTARTNOINTR:
541                                 regs->regs[0] = orig_r0;
542                                 regs->pc -= 2;
543                 }
544         } else {
545                 /* gUSA handling */
546                 if (regs->regs[15] >= 0xc0000000) {
547                         int offset = (int)regs->regs[15];
548 
549                         /* Reset stack pointer: clear critical region mark */
550                         regs->regs[15] = regs->regs[1];
551                         if (regs->pc < regs->regs[0])
552                                 /* Go to rewind point #1 */
553                                 regs->pc = regs->regs[0] + offset - 2;
554                 }
555         }
556 
557         /* Set up the stack frame */
558         if (ka->sa.sa_flags & SA_SIGINFO)
559                 setup_rt_frame(sig, ka, info, oldset, regs);
560         else
561                 setup_frame(sig, ka, oldset, regs);
562 
563         if (ka->sa.sa_flags & SA_ONESHOT)
564                 ka->sa.sa_handler = SIG_DFL;
565 
566         if (!(ka->sa.sa_flags & SA_NODEFER)) {
567                 spin_lock_irq(&current->sigmask_lock);
568                 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
569                 sigaddset(&current->blocked,sig);
570                 recalc_sigpending(current);
571                 spin_unlock_irq(&current->sigmask_lock);
572         }
573 }
574 
575 /*
576  * Note that 'init' is a special process: it doesn't get signals it doesn't
577  * want to handle. Thus you cannot kill init even with a SIGKILL even by
578  * mistake.
579  *
580  * Note that we go through the signals twice: once to check the signals that
581  * the kernel can handle, and then we build all the user-level signal handling
582  * stack-frames in one go after that.
583  */
584 int do_signal(struct pt_regs *regs, sigset_t *oldset,
585               int from_syscall, unsigned long orig_r0)
586 {
587         siginfo_t info;
588         struct k_sigaction *ka;
589 
590         /*
591          * We want the common case to go fast, which
592          * is why we may in certain cases get here from
593          * kernel mode. Just return without doing anything
594          * if so.
595          */
596         if (!user_mode(regs))
597                 return 1;
598 
599         if (!oldset)
600                 oldset = &current->blocked;
601 
602         for (;;) {
603                 unsigned long signr;
604 
605                 spin_lock_irq(&current->sigmask_lock);
606                 signr = dequeue_signal(&current->blocked, &info);
607                 spin_unlock_irq(&current->sigmask_lock);
608 
609                 if (!signr)
610                         break;
611 
612                 if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
613                         /* Let the debugger run.  */
614                         current->exit_code = signr;
615                         current->state = TASK_STOPPED;
616                         notify_parent(current, SIGCHLD);
617                         schedule();
618 
619                         /* We're back.  Did the debugger cancel the sig?  */
620                         if (!(signr = current->exit_code))
621                                 continue;
622                         current->exit_code = 0;
623 
624                         /* The debugger continued.  Ignore SIGSTOP.  */
625                         if (signr == SIGSTOP)
626                                 continue;
627 
628                         /* Update the siginfo structure.  Is this good?  */
629                         if (signr != info.si_signo) {
630                                 info.si_signo = signr;
631                                 info.si_errno = 0;
632                                 info.si_code = SI_USER;
633                                 info.si_pid = current->p_pptr->pid;
634                                 info.si_uid = current->p_pptr->uid;
635                         }
636 
637                         /* If the (new) signal is now blocked, requeue it.  */
638                         if (sigismember(&current->blocked, signr)) {
639                                 send_sig_info(signr, &info, current);
640                                 continue;
641                         }
642                 }
643 
644                 ka = &current->sig->action[signr-1];
645                 if (ka->sa.sa_handler == SIG_IGN) {
646                         if (signr != SIGCHLD)
647                                 continue;
648                         /* Check for SIGCHLD: it's special.  */
649                         while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
650                                 /* nothing */;
651                         continue;
652                 }
653 
654                 if (ka->sa.sa_handler == SIG_DFL) {
655                         int exit_code = signr;
656 
657                         /* Init gets no signals it doesn't want.  */
658                         if (current->pid == 1)
659                                 continue;
660 
661                         switch (signr) {
662                         case SIGCONT: case SIGCHLD: case SIGWINCH:
663                                 continue;
664 
665                         case SIGTSTP: case SIGTTIN: case SIGTTOU:
666                                 if (is_orphaned_pgrp(current->pgrp))
667                                         continue;
668                                 /* FALLTHRU */
669 
670                         case SIGSTOP:
671                                 current->state = TASK_STOPPED;
672                                 current->exit_code = signr;
673                                 if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
674                                         notify_parent(current, SIGCHLD);
675                                 schedule();
676                                 continue;
677 
678                         case SIGQUIT: case SIGILL: case SIGTRAP:
679                         case SIGABRT: case SIGFPE: case SIGSEGV:
680                         case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
681                                 if (do_coredump(signr, regs))
682                                         exit_code |= 0x80;
683                                 /* FALLTHRU */
684 
685                         default:
686                                 sig_exit(signr, exit_code, &info);
687                                 /* NOTREACHED */
688                         }
689                 }
690 
691                 /* Whee!  Actually deliver the signal.  */
692                 handle_signal(signr, ka, &info, oldset, regs,
693                               from_syscall, orig_r0);
694                 return 1;
695         }
696 
697         /* Did we come from a system call? */
698         if (from_syscall) {
699                 /* Restart the system call - no handlers present */
700                 if (regs->regs[0] == -ERESTARTNOHAND ||
701                     regs->regs[0] == -ERESTARTSYS ||
702                     regs->regs[0] == -ERESTARTNOINTR) {
703                         regs->regs[0] = orig_r0;
704                         regs->pc -= 2;
705                 }
706         }
707         return 0;
708 }
709 

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