1 /* $NetBSD: signals.c,v 1.16 2016/01/26 23:12:18 pooka Exp $ */
2
3 /*-
4 * Copyright (c) 2010, 2011 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.16 2016/01/26 23:12:18 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-sys/kern.h>
38
39 #include <rump/rump.h>
40 #include <rump/rumpuser.h>
41
42 const struct filterops sig_filtops = {
43 .f_attach = (void *)eopnotsupp,
44 };
45
46 sigset_t sigcantmask;
47
48 static void
pgrp_apply(struct pgrp * pgrp,int signo,void (* apply)(struct proc * p,int))49 pgrp_apply(struct pgrp *pgrp, int signo, void (*apply)(struct proc *p, int))
50 {
51 struct proc *p;
52
53 KASSERT(mutex_owned(proc_lock));
54
55 LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
56 mutex_enter(p->p_lock);
57 apply(p, signo);
58 mutex_exit(p->p_lock);
59 }
60 }
61
62 /* RUMP_SIGMODEL_PANIC */
63
64 static void
rumpsig_panic(struct proc * p,int signo)65 rumpsig_panic(struct proc *p, int signo)
66 {
67
68 switch (signo) {
69 case SIGSYS:
70 case SIGPIPE:
71 break;
72 default:
73 panic("unhandled signal %d", signo);
74 }
75 }
76
77 /* RUMP_SIGMODEL_IGNORE */
78
79 static void
rumpsig_ignore(struct proc * p,int signo)80 rumpsig_ignore(struct proc *p, int signo)
81 {
82
83 return;
84 }
85
86 /* RUMP_SIGMODEL_RAISE */
87
88 static void
rumpsig_raise(struct proc * p,int signo)89 rumpsig_raise(struct proc *p, int signo)
90 {
91
92 if (RUMP_LOCALPROC_P(p)) {
93 rumpuser_kill(p->p_pid, signo);
94 } else {
95 rump_sysproxy_raise(RUMP_SPVM2CTL(p->p_vmspace), signo);
96 }
97 }
98
99 static void
rumpsig_record(struct proc * p,int signo)100 rumpsig_record(struct proc *p, int signo)
101 {
102
103 if (!sigismember(&p->p_sigctx.ps_sigignore, signo)) {
104 sigaddset(&p->p_sigpend.sp_set, signo);
105 }
106 }
107
108 typedef void (*rumpsig_fn)(struct proc *, int);
109
110 static rumpsig_fn rumpsig = rumpsig_raise;
111
112 /*
113 * Set signal delivery model. It would be nice if we could
114 * take a functional argument. But then we'd need some
115 * OS independent way to represent a signal number and also
116 * a method for easy processing (parsing is boring).
117 *
118 * Plus, upcalls from the rump kernel into process space except
119 * via rumpuser is a somewhat gray area now.
120 */
121 void
rump_boot_setsigmodel(enum rump_sigmodel model)122 rump_boot_setsigmodel(enum rump_sigmodel model)
123 {
124
125 switch (model) {
126 case RUMP_SIGMODEL_PANIC:
127 rumpsig = rumpsig_panic;
128 break;
129 case RUMP_SIGMODEL_IGNORE:
130 rumpsig = rumpsig_ignore;
131 break;
132 case RUMP_SIGMODEL_RAISE:
133 rumpsig = rumpsig_raise;
134 break;
135 case RUMP_SIGMODEL_RECORD:
136 rumpsig = rumpsig_record;
137 break;
138
139 /* for compat, though I doubt anyone is using it */
140 case RUMP_SIGMODEL__HOST_NOTANYMORE:
141 rumpsig = rumpsig_raise;
142 break;
143 }
144 }
145
146 void
psignal(struct proc * p,int sig)147 psignal(struct proc *p, int sig)
148 {
149
150 rumpsig(p, sig);
151 }
152
153 void
pgsignal(struct pgrp * pgrp,int sig,int checktty)154 pgsignal(struct pgrp *pgrp, int sig, int checktty)
155 {
156
157 pgrp_apply(pgrp, sig, rumpsig);
158 }
159
160 void
kpsignal(struct proc * p,ksiginfo_t * ksi,void * data)161 kpsignal(struct proc *p, ksiginfo_t *ksi, void *data)
162 {
163
164 rumpsig(p, ksi->ksi_signo);
165 }
166
167 void
kpgsignal(struct pgrp * pgrp,ksiginfo_t * ksi,void * data,int checkctty)168 kpgsignal(struct pgrp *pgrp, ksiginfo_t *ksi, void *data, int checkctty)
169 {
170
171 pgrp_apply(pgrp, ksi->ksi_signo, rumpsig);
172 }
173
174 int
sigispending(struct lwp * l,int signo)175 sigispending(struct lwp *l, int signo)
176 {
177 struct proc *p = l->l_proc;
178 sigset_t tset;
179
180 tset = p->p_sigpend.sp_set;
181
182 if (signo == 0) {
183 if (firstsig(&tset) != 0)
184 return EINTR;
185 } else if (sigismember(&tset, signo))
186 return EINTR;
187 return 0;
188 }
189
190 void
sigpending1(struct lwp * l,sigset_t * ss)191 sigpending1(struct lwp *l, sigset_t *ss)
192 {
193 struct proc *p = l->l_proc;
194
195 mutex_enter(p->p_lock);
196 *ss = l->l_proc->p_sigpend.sp_set;
197 mutex_exit(p->p_lock);
198 }
199
200 int
sigismasked(struct lwp * l,int sig)201 sigismasked(struct lwp *l, int sig)
202 {
203
204 return sigismember(&l->l_proc->p_sigctx.ps_sigignore, sig);
205 }
206
207 void
sigclear(sigpend_t * sp,const sigset_t * mask,ksiginfoq_t * kq)208 sigclear(sigpend_t *sp, const sigset_t *mask, ksiginfoq_t *kq)
209 {
210
211 if (mask == NULL)
212 sigemptyset(&sp->sp_set);
213 else
214 sigminusset(mask, &sp->sp_set);
215 }
216
217 void
sigclearall(struct proc * p,const sigset_t * mask,ksiginfoq_t * kq)218 sigclearall(struct proc *p, const sigset_t *mask, ksiginfoq_t *kq)
219 {
220
221 /* don't assert proc lock, hence callable from user context */
222 sigclear(&p->p_sigpend, mask, kq);
223 }
224
225 void
ksiginfo_queue_drain0(ksiginfoq_t * kq)226 ksiginfo_queue_drain0(ksiginfoq_t *kq)
227 {
228
229 if (!(TAILQ_EMPTY(kq)))
230 panic("how did that get there?");
231 }
232
233 int
sigprocmask1(struct lwp * l,int how,const sigset_t * nss,sigset_t * oss)234 sigprocmask1(struct lwp *l, int how, const sigset_t *nss, sigset_t *oss)
235 {
236 sigset_t *mask = &l->l_proc->p_sigctx.ps_sigignore;
237
238 KASSERT(mutex_owned(l->l_proc->p_lock));
239
240 if (oss)
241 *oss = *mask;
242
243 if (nss) {
244 switch (how) {
245 case SIG_BLOCK:
246 sigplusset(nss, mask);
247 break;
248 case SIG_UNBLOCK:
249 sigminusset(nss, mask);
250 break;
251 case SIG_SETMASK:
252 *mask = *nss;
253 break;
254 default:
255 return EINVAL;
256 }
257 }
258
259 return 0;
260 }
261
262 void
siginit(struct proc * p)263 siginit(struct proc *p)
264 {
265
266 sigemptyset(&p->p_sigctx.ps_sigignore);
267 sigemptyset(&p->p_sigpend.sp_set);
268 }
269
270 void
sigsuspendsetup(struct lwp * l,const sigset_t * ss)271 sigsuspendsetup(struct lwp *l, const sigset_t *ss)
272 {
273 /* XXX: Partial copy of kernel code, remove and use the kernel code. */
274 struct proc *p = l->l_proc;
275
276 mutex_enter(p->p_lock);
277 l->l_sigrestore = 1;
278 l->l_sigoldmask = l->l_sigmask;
279 l->l_sigmask = *ss;
280 sigminusset(&sigcantmask, &l->l_sigmask);
281 mutex_exit(p->p_lock);
282 }
283
284 void
sigsuspendteardown(struct lwp * l)285 sigsuspendteardown(struct lwp *l)
286 {
287 /* XXX: Copy of kernel code, remove and use the kernel code. */
288 struct proc *p = l->l_proc;
289
290 mutex_enter(p->p_lock);
291 if (l->l_sigrestore) {
292 l->l_sigrestore = 0;
293 l->l_sigmask = l->l_sigoldmask;
294 }
295 mutex_exit(p->p_lock);
296 }
297