Prex Home / Browse Source - Prex Version: 0.9.0

root/usr/server/proc/proc_sig.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. kill_capable
  2. sendsig
  3. kill_one
  4. kill_pg
  5. sys_kill

   1 /*
   2  * Copyright (c) 2005-2006, Kohsuke Ohtani
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  * 3. Neither the name of the author nor the names of any co-contributors
  14  *    may be used to endorse or promote products derived from this software
  15  *    without specific prior written permission.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  */
  29 
  30 /*
  31  * proc_sig.c - signal transfer.
  32  */
  33 
  34 #include <sys/prex.h>
  35 #include <sys/capability.h>
  36 #include <ipc/proc.h>
  37 #include <sys/list.h>
  38 
  39 #include <unistd.h>
  40 #include <errno.h>
  41 
  42 #include "proc.h"
  43 
  44 /*
  45  * Check if current process has CAP_KILL capability.
  46  */
  47 static int
  48 kill_capable(void)
  49 {
  50 
  51         if (task_chkcap(curproc->p_task, CAP_KILL) == 0)
  52                 return 1;
  53         return 0;
  54 }
  55 
  56 /*
  57  * Send a signal to the process.
  58  */
  59 static int
  60 sendsig(struct proc *p, int sig)
  61 {
  62 
  63         /*
  64          * We never allow to send signal to the
  65          * process server in any case.
  66          */
  67         if (p->p_pid == 0)
  68                 return EPERM;
  69 
  70         /*
  71          * Filter signals for init process.
  72          * This is for fail safe...
  73          */
  74         if (p->p_pid == 1 && sig != SIGCHLD)
  75                 return EPERM;
  76 
  77         DPRINTF(("proc: sendsig task=%x\n", p->p_task));
  78         return exception_raise(p->p_task, sig);
  79 }
  80 
  81 /*
  82  * Send a signal to one process.
  83  */
  84 static int
  85 kill_one(pid_t pid, int sig)
  86 {
  87         struct proc *p;
  88 
  89         DPRINTF(("proc: killone pid=%d sig=%d\n", pid, sig));
  90 
  91         if ((p = p_find(pid)) == NULL)
  92                 return ESRCH;
  93         return sendsig(p, sig);
  94 }
  95 
  96 /*
  97  * Send a signal to all process in the process group.
  98  */
  99 int
 100 kill_pg(pid_t pgid, int sig)
 101 {
 102         struct proc *p;
 103         struct pgrp *pgrp;
 104         list_t head, n;
 105         int error = 0;
 106 
 107         DPRINTF(("proc: killpg pgid=%d sig=%d\n", pgid, sig));
 108 
 109         if ((pgrp = pg_find(pgid)) == NULL)
 110                 return ESRCH;
 111 
 112         head = &pgrp->pg_members;
 113         for (n = list_first(head); n != head; n = list_next(n)) {
 114                 p = list_entry(n, struct proc, p_pgrp_link);
 115                 if ((error = sendsig(p, sig)) != 0)
 116                         break;
 117         }
 118         return error;
 119 }
 120 
 121 /*
 122  * Send a signal.
 123  *
 124  * The behavior is different for the pid value.
 125  *
 126  *  if (pid > 0)
 127  *    Send a signal to specific process.
 128  *
 129  *  if (pid == 0)
 130  *    Send a signal to all processes in same process group.
 131  *
 132  *  if (pid == -1)
 133  *    Send a signal to all processes except init.
 134  *
 135  *  if (pid < -1)
 136  *     Send a signal to the process group.
 137  *
 138  * Note: Need CAP_KILL capability to send a signal to the different
 139  * process/group.
 140  */
 141 int
 142 sys_kill(pid_t pid, int sig)
 143 {
 144         struct proc *p;
 145         list_t n;
 146         int error = 0;
 147 
 148         DPRINTF(("proc: kill pid=%d sig=%d\n", pid, sig));
 149 
 150         switch (sig) {
 151         case SIGFPE:
 152         case SIGILL:
 153         case SIGSEGV:
 154                 return EINVAL;
 155         }
 156 
 157         if (pid > 0) {
 158                 if (pid != curproc->p_pid && !kill_capable()) {
 159                         DPRINTF(("proc: EPERM\n"));
 160                         return EPERM;
 161                 }
 162                 error = kill_one(pid, sig);
 163         }
 164         else if (pid == -1) {
 165                 DPRINTF(("proc: kill? curproc=%x\n", curproc));
 166                 if (!kill_capable())
 167                         return EPERM;
 168 
 169                 DPRINTF(("proc: kill all!\n"));
 170                 for (n = list_first(&allproc); n != &allproc;
 171                      n = list_next(n)) {
 172                         p = list_entry(n, struct proc, p_link);
 173 
 174                         /*
 175                          * We don't send a signal to the following processes.
 176                          *
 177                          *  pid=0   - process server
 178                          *  pid=1   - init process
 179                          *  curproc - current process (sleeping in msg_send)
 180                          */
 181                         if (p->p_pid != 0 && p->p_pid != 1 &&
 182                             p->p_pid != curproc->p_pid)
 183                         {
 184                                 error = kill_one(p->p_pid, sig);
 185                                 if (error != 0)
 186                                         break;
 187                         }
 188                 }
 189         }
 190         else if (pid == 0) {
 191                 error = kill_pg(curproc->p_pgrp->pg_pgid, sig);
 192         }
 193         else {  /* pid < -1 */
 194                 if (curproc->p_pgrp->pg_pgid != -pid && !kill_capable())
 195                         return EPERM;
 196                 error = kill_pg(-pid, sig);
 197         }
 198         return error;
 199 }

/* [<][>][^][v][top][bottom][index][help] */