Diff for /linux/kernel/signal.c between versions 1.1 and 1.1.1.8

version 1.1, 2018/04/24 18:01:38 version 1.1.1.8, 2018/04/24 18:15:15
Line 1 Line 1
 /*  /*
  *  linux/kernel/signal.c   *  linux/kernel/signal.c
  *   *
  *  (C) 1991  Linus Torvalds   *  Copyright (C) 1991, 1992  Linus Torvalds
  */   */
   
 #include <linux/sched.h>  #include <linux/sched.h>
 #include <linux/kernel.h>  #include <linux/kernel.h>
 #include <asm/segment.h>  #include <linux/signal.h>
   #include <linux/errno.h>
   #include <linux/wait.h>
   #include <linux/ptrace.h>
   
 #include <signal.h>  #include <asm/segment.h>
   
 volatile void do_exit(int error_code);  extern int core_dump(long signr,struct pt_regs * regs);
   
 int sys_sgetmask()  int sys_sgetmask()
 {  {
Line 21  int sys_ssetmask(int newmask) Line 24  int sys_ssetmask(int newmask)
 {  {
         int old=current->blocked;          int old=current->blocked;
   
         current->blocked = newmask & ~(1<<(SIGKILL-1));          current->blocked = newmask & ~(1<<(SIGKILL-1)) & ~(1<<(SIGSTOP-1));
         return old;          return old;
 }  }
   
   int sys_sigpending(sigset_t *set)
   {
       /* fill in "set" with signals pending but blocked. */
       verify_area(set,4);
       put_fs_long(current->blocked & current->signal, (unsigned long *)set);
       return 0;
   }
   
   /* atomically swap in the new signal mask, and wait for a signal.
    *
    * we need to play some games with syscall restarting.  We get help
    * from the syscall library interface.  Note that we need to coordinate
    * the calling convention with the libc routine.
    *
    * "set" is just the sigmask as described in 1003.1-1988, 3.3.7.
    *      It is assumed that sigset_t can be passed as a 32 bit quantity.
    *
    * "restart" holds a restart indication.  If it's non-zero, then we 
    *      install the old mask, and return normally.  If it's zero, we store 
    *      the current mask in old_mask and block until a signal comes in.
    */
   int sys_sigsuspend(int restart, unsigned long old_mask, unsigned long set)
   {
       extern int sys_pause(void);
   
       if (restart) {
           /* we're restarting */
           current->blocked = old_mask;
           return -EINTR;
       }
       /* we're not restarting.  do the work */
       *(&restart) = 1;
       *(&old_mask) = current->blocked;
       current->blocked = set;
       (void) sys_pause();                 /* return after a signal arrives */
       return -ERESTARTNOINTR;             /* handle the signal, and come back */
   }
   
 static inline void save_old(char * from,char * to)  static inline void save_old(char * from,char * to)
 {  {
         int i;          int i;
Line 49  int sys_signal(int signum, long handler, Line 90  int sys_signal(int signum, long handler,
 {  {
         struct sigaction tmp;          struct sigaction tmp;
   
         if (signum<1 || signum>32 || signum==SIGKILL)          if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP)
                 return -1;                  return -EINVAL;
         tmp.sa_handler = (void (*)(int)) handler;          tmp.sa_handler = (void (*)(int)) handler;
         tmp.sa_mask = 0;          tmp.sa_mask = 0;
         tmp.sa_flags = SA_ONESHOT | SA_NOMASK;          tmp.sa_flags = SA_ONESHOT | SA_NOMASK | SA_INTERRUPT;
         tmp.sa_restorer = (void (*)(void)) restorer;          tmp.sa_restorer = (void (*)(void)) restorer;
         handler = (long) current->sigaction[signum-1].sa_handler;          handler = (long) current->sigaction[signum-1].sa_handler;
         current->sigaction[signum-1] = tmp;          current->sigaction[signum-1] = tmp;
Line 65  int sys_sigaction(int signum, const stru Line 106  int sys_sigaction(int signum, const stru
 {  {
         struct sigaction tmp;          struct sigaction tmp;
   
         if (signum<1 || signum>32 || signum==SIGKILL)          if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP)
                 return -1;                  return -EINVAL;
         tmp = current->sigaction[signum-1];          tmp = current->sigaction[signum-1];
         get_new((char *) action,          get_new((char *) action,
                 (char *) (signum-1+current->sigaction));                  (char *) (signum-1+current->sigaction));
Line 79  int sys_sigaction(int signum, const stru Line 120  int sys_sigaction(int signum, const stru
         return 0;          return 0;
 }  }
   
 void do_signal(long signr,long eax, long ebx, long ecx, long edx,  extern int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
         long fs, long es, long ds,  
         long eip, long cs, long eflags,  /*
         unsigned long * esp, long ss)   * Note that 'init' is a special process: it doesn't get signals it doesn't
    * want to handle. Thus you cannot kill init even with a SIGKILL even by
    * mistake.
    */
   int do_signal(long signr,struct pt_regs * regs)
 {  {
         long sa_handler;          unsigned long sa_handler;
         long old_eip=eip;          long old_eip = regs->eip;
         struct sigaction * sa = current->sigaction + signr - 1;          struct sigaction * sa = current->sigaction + signr - 1;
         int longs;          int longs;
         unsigned long * tmp_esp;          unsigned long * tmp_esp;
   
         sa_handler = (long) sa->sa_handler;          sa_handler = (unsigned long) sa->sa_handler;
         if (sa_handler==1)          if ((regs->orig_eax >= 0) &&
                 return;              ((regs->eax == -ERESTARTSYS) || (regs->eax == -ERESTARTNOINTR))) {
                   if ((sa_handler > 1) && (regs->eax == -ERESTARTSYS) &&
                       (sa->sa_flags & SA_INTERRUPT))
                           regs->eax = -EINTR;
                   else {
                           regs->eax = regs->orig_eax;
                           regs->eip = old_eip -= 2;
                   }
           }
           if (sa_handler==1) {
   /* check for SIGCHLD: it's special */
                   if (signr == SIGCHLD)
                           while (sys_waitpid(-1,NULL,WNOHANG) > 0)
                                   /* nothing */;
                   return(1);   /* Ignore, see if there are more signals... */
           }
         if (!sa_handler) {          if (!sa_handler) {
                 if (signr==SIGCHLD)                  if (current->pid == 1)
                         return;                          return 1;
                 else                  switch (signr) {
                         do_exit(1<<(signr-1));                  case SIGCONT:
                   case SIGCHLD:
                   case SIGWINCH:
                           return(1);  /* Ignore, ... */
   
                   case SIGSTOP:
                   case SIGTSTP:
                   case SIGTTIN:
                   case SIGTTOU:
                           current->state = TASK_STOPPED;
                           current->exit_code = signr;
                           if (!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags & 
                                           SA_NOCLDSTOP))
                                   send_sig(SIGCHLD, current->p_pptr, 1);                  
                           return(1);  /* Reschedule another event */
   
                   case SIGQUIT:
                   case SIGILL:
                   case SIGTRAP:
                   case SIGIOT:
                   case SIGFPE:
                   case SIGSEGV:
                           if (core_dump(signr,regs))
                                   signr |= 0x80;
                           /* fall through */
                   default:
                           current->signal |= 1<<((signr & 0x7f)-1);
                           do_exit(signr);
                   }
         }          }
           /*
            * OK, we're invoking a handler 
            */
         if (sa->sa_flags & SA_ONESHOT)          if (sa->sa_flags & SA_ONESHOT)
                 sa->sa_handler = NULL;                  sa->sa_handler = NULL;
         *(&eip) = sa_handler;          regs->eip = sa_handler;
         longs = (sa->sa_flags & SA_NOMASK)?7:8;          longs = (sa->sa_flags & SA_NOMASK)?(7*4):(8*4);
         *(&esp) -= longs;          regs->esp -= longs;
         verify_area(esp,longs*4);          tmp_esp = (unsigned long *) regs->esp;
         tmp_esp=esp;          verify_area(tmp_esp,longs);
         put_fs_long((long) sa->sa_restorer,tmp_esp++);          put_fs_long((long) sa->sa_restorer,tmp_esp++);
         put_fs_long(signr,tmp_esp++);          put_fs_long(signr,tmp_esp++);
         if (!(sa->sa_flags & SA_NOMASK))          if (!(sa->sa_flags & SA_NOMASK))
                 put_fs_long(current->blocked,tmp_esp++);                  put_fs_long(current->blocked,tmp_esp++);
         put_fs_long(eax,tmp_esp++);          put_fs_long(regs->eax,tmp_esp++);
         put_fs_long(ecx,tmp_esp++);          put_fs_long(regs->ecx,tmp_esp++);
         put_fs_long(edx,tmp_esp++);          put_fs_long(regs->edx,tmp_esp++);
         put_fs_long(eflags,tmp_esp++);          put_fs_long(regs->eflags,tmp_esp++);
         put_fs_long(old_eip,tmp_esp++);          put_fs_long(old_eip,tmp_esp++);
         current->blocked |= sa->sa_mask;          current->blocked |= sa->sa_mask;
   /* force a supervisor-mode page-in of the signal handler to reduce races */
           __asm__("testb $0,%%fs:%0"::"m" (*(char *) sa_handler));
           return(0);              /* Continue, execute handler */
 }  }

Removed from v.1.1  
changed lines
  Added in v.1.1.1.8


unix.superglobalmegacorp.com