Statistics
| Branch: | Revision:

scoutos / prex-0.9.0 / usr / server / proc / proc_sig.c @ 03e9c04a

History | View | Annotate | Download (4.61 KB)

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
}