1/*	$NetBSD: signals.c,v 1.17 2020/05/23 23:42:44 ad 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.17 2020/05/23 23:42:44 ad 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
42const struct filterops sig_filtops = {
43	.f_attach = (void *)eopnotsupp,
44};
45
46sigset_t sigcantmask;
47
48static void
49pgrp_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
64static void
65rumpsig_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
79static void
80rumpsig_ignore(struct proc *p, int signo)
81{
82
83	return;
84}
85
86/* RUMP_SIGMODEL_RAISE */
87
88static void
89rumpsig_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
99static void
100rumpsig_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
108typedef void (*rumpsig_fn)(struct proc *, int);
109
110static 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 */
121void
122rump_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
146void
147psignal(struct proc *p, int sig)
148{
149
150	rumpsig(p, sig);
151}
152
153void
154pgsignal(struct pgrp *pgrp, int sig, int checktty)
155{
156
157	pgrp_apply(pgrp, sig, rumpsig);
158}
159
160void
161kpsignal(struct proc *p, ksiginfo_t *ksi, void *data)
162{
163
164	rumpsig(p, ksi->ksi_signo);
165}
166
167void
168kpgsignal(struct pgrp *pgrp, ksiginfo_t *ksi, void *data, int checkctty)
169{
170
171	pgrp_apply(pgrp, ksi->ksi_signo, rumpsig);
172}
173
174int
175sigispending(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
190void
191sigpending1(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
200int
201sigismasked(struct lwp *l, int sig)
202{
203
204	return sigismember(&l->l_proc->p_sigctx.ps_sigignore, sig);
205}
206
207void
208sigclear(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
217void
218sigclearall(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
225void
226ksiginfo_queue_drain0(ksiginfoq_t *kq)
227{
228
229	if (!(TAILQ_EMPTY(kq)))
230		panic("how did that get there?");
231}
232
233int
234sigprocmask1(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
262void
263siginit(struct proc *p)
264{
265
266	sigemptyset(&p->p_sigctx.ps_sigignore);
267	sigemptyset(&p->p_sigpend.sp_set);
268}
269
270void
271sigsuspendsetup(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
284void
285sigsuspendteardown(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