signals.c revision 1.5 1 /* $NetBSD: signals.c,v 1.5 2011/01/03 14:57:06 pooka Exp $ */
2
3 /*
4 * Copyright (c) 2010 Antti Kantee. All Rights Reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: signals.c,v 1.5 2011/01/03 14:57:06 pooka Exp $");
30
31 #include <sys/param.h>
32 #include <sys/atomic.h>
33 #include <sys/event.h>
34 #include <sys/proc.h>
35 #include <sys/signal.h>
36
37 #include <rump/rump.h>
38 #include <rump/rumpuser.h>
39
40 #include "rumpkern_if_priv.h"
41
42 const struct filterops sig_filtops = {
43 .f_attach = (void *)eopnotsupp,
44 };
45
46 sigset_t sigcantmask;
47
48 /* RUMP_SIGMODEL_PANIC */
49
50 static void
51 rumpsig_panic(pid_t target, int signo)
52 {
53
54 switch (signo) {
55 case SIGSYS:
56 break;
57 default:
58 panic("unhandled signal %d", signo);
59 }
60 }
61
62 /* RUMP_SIGMODEL_IGNORE */
63
64 static void
65 rumpsig_ignore(pid_t target, int signo)
66 {
67
68 return;
69 }
70
71 /* RUMP_SIGMODEL_HOST */
72
73 static void
74 rumpsig_host(pid_t target, int signo)
75 {
76 int error;
77
78 rumpuser_kill(target, signo, &error);
79 }
80
81 /* RUMP_SIGMODEL_RAISE */
82
83 static void
84 rumpsig_raise(pid_t target, int signo)
85 {
86 int error;
87
88 rumpuser_kill(RUMPUSER_PID_SELF, signo, &error);
89 }
90
91 static void
92 rumpsig_record(pid_t target, int sig)
93 {
94 struct proc *p = NULL;
95 struct pgrp *pgrp = NULL;
96
97 /* well this is a little silly */
98 mutex_enter(proc_lock);
99 if (target >= 0)
100 p = proc_find_raw(target);
101 else
102 pgrp = pgrp_find(target);
103
104 if (p) {
105 mutex_enter(p->p_lock);
106 if (!sigismember(&p->p_sigctx.ps_sigignore, sig)) {
107 sigaddset(&p->p_sigpend.sp_set, sig);
108 }
109 mutex_exit(p->p_lock);
110 } else if (pgrp) {
111 LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
112 mutex_enter(p->p_lock);
113 if (!sigismember(&p->p_sigctx.ps_sigignore, sig)) {
114 sigaddset(&p->p_sigpend.sp_set, sig);
115 }
116 mutex_exit(p->p_lock);
117 }
118 }
119 mutex_exit(proc_lock);
120 }
121
122 typedef void (*rumpsig_fn)(pid_t pid, int sig);
123
124 rumpsig_fn rumpsig = rumpsig_panic;
125
126 /*
127 * Set signal delivery model. It would be nice if we could
128 * take a functional argument. But then we'd need some
129 * OS independent way to represent a signal number and also
130 * a method for easy processing (parsing is boring).
131 *
132 * Plus, upcalls from the rump kernel into process space except
133 * via rumpuser is a somewhat gray area now.
134 */
135 void
136 rump_boot_setsigmodel(enum rump_sigmodel model)
137 {
138
139 switch (model) {
140 case RUMP_SIGMODEL_PANIC:
141 rumpsig = rumpsig_panic;
142 break;
143 case RUMP_SIGMODEL_IGNORE:
144 rumpsig = rumpsig_ignore;
145 break;
146 case RUMP_SIGMODEL_HOST:
147 rumpsig = rumpsig_host;
148 break;
149 case RUMP_SIGMODEL_RAISE:
150 rumpsig = rumpsig_raise;
151 break;
152 case RUMP_SIGMODEL_RECORD:
153 rumpsig = rumpsig_record;
154 break;
155 }
156 }
157
158 void
159 psignal(struct proc *p, int sig)
160 {
161
162 rumpsig(p->p_pid, sig);
163 }
164
165 void
166 pgsignal(struct pgrp *pgrp, int sig, int checktty)
167 {
168
169 rumpsig(-pgrp->pg_id, sig);
170 }
171
172 void
173 kpsignal(struct proc *p, ksiginfo_t *ksi, void *data)
174 {
175
176 rumpsig(p->p_pid, ksi->ksi_signo);
177 }
178
179 void
180 kpgsignal(struct pgrp *pgrp, ksiginfo_t *ksi, void *data, int checkctty)
181 {
182
183 rumpsig(-pgrp->pg_id, ksi->ksi_signo);
184 }
185
186 int
187 sigispending(struct lwp *l, int signo)
188 {
189 struct proc *p = l->l_proc;
190 sigset_t tset;
191
192 tset = p->p_sigpend.sp_set;
193
194 if (signo == 0) {
195 if (firstsig(&tset) != 0)
196 return EINTR;
197 } else if (sigismember(&tset, signo))
198 return EINTR;
199 return 0;
200 }
201
202 void
203 sigpending1(struct lwp *l, sigset_t *ss)
204 {
205 struct proc *p = l->l_proc;
206
207 mutex_enter(p->p_lock);
208 *ss = l->l_proc->p_sigpend.sp_set;
209 mutex_exit(p->p_lock);
210 }
211
212 int
213 sigismasked(struct lwp *l, int sig)
214 {
215
216 return sigismember(&l->l_proc->p_sigctx.ps_sigignore, sig);
217 }
218
219 void
220 sigclear(sigpend_t *sp, const sigset_t *mask, ksiginfoq_t *kq)
221 {
222
223 if (mask == NULL)
224 sigemptyset(&sp->sp_set);
225 else
226 sigminusset(mask, &sp->sp_set);
227 }
228
229 void
230 sigclearall(struct proc *p, const sigset_t *mask, ksiginfoq_t *kq)
231 {
232
233 /* don't assert proc lock, hence callable from user context */
234 sigclear(&p->p_sigpend, mask, kq);
235 }
236
237 void
238 ksiginfo_queue_drain0(ksiginfoq_t *kq)
239 {
240
241 if (!(CIRCLEQ_EMPTY(kq)))
242 panic("how did that get there?");
243 }
244
245 int
246 sigprocmask1(struct lwp *l, int how, const sigset_t *nss, sigset_t *oss)
247 {
248 sigset_t *mask = &l->l_proc->p_sigctx.ps_sigignore;
249
250 KASSERT(mutex_owned(l->l_proc->p_lock));
251
252 if (oss)
253 *oss = *mask;
254
255 if (nss) {
256 switch (how) {
257 case SIG_BLOCK:
258 sigplusset(nss, mask);
259 break;
260 case SIG_UNBLOCK:
261 sigminusset(nss, mask);
262 break;
263 case SIG_SETMASK:
264 *mask = *nss;
265 break;
266 default:
267 return EINVAL;
268 }
269 }
270
271 return 0;
272 }
273
274 void
275 siginit(struct proc *p)
276 {
277
278 sigemptyset(&p->p_sigctx.ps_sigignore);
279 sigemptyset(&p->p_sigpend.sp_set);
280 }
281