ibcs2_signal.c revision 331643
1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1995 Scott Bartram
5 * Copyright (c) 1995 Steven Wallace
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 *    derived from this software without specific prior written permission
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: stable/11/sys/i386/ibcs2/ibcs2_signal.c 331643 2018-03-27 18:52:27Z dim $");
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/lock.h>
37#include <sys/mutex.h>
38#include <sys/signalvar.h>
39#include <sys/syscallsubr.h>
40#include <sys/sysproto.h>
41
42#include <i386/ibcs2/ibcs2_types.h>
43#include <i386/ibcs2/ibcs2_signal.h>
44#include <i386/ibcs2/ibcs2_proto.h>
45#include <i386/ibcs2/ibcs2_xenix.h>
46#include <i386/ibcs2/ibcs2_util.h>
47
48#define sigemptyset(s)		SIGEMPTYSET(*(s))
49#define sigismember(s, n)	SIGISMEMBER(*(s), n)
50#define sigaddset(s, n)		SIGADDSET(*(s), n)
51
52#define	ibcs2_sigmask(n)	(1 << ((n) - 1))
53#define ibcs2_sigemptyset(s)	bzero((s), sizeof(*(s)))
54#define ibcs2_sigismember(s, n)	(*(s) & ibcs2_sigmask(n))
55#define ibcs2_sigaddset(s, n)	(*(s) |= ibcs2_sigmask(n))
56
57static void ibcs2_to_bsd_sigset(const ibcs2_sigset_t *, sigset_t *);
58static void bsd_to_ibcs2_sigset(const sigset_t *, ibcs2_sigset_t *);
59static void ibcs2_to_bsd_sigaction(struct ibcs2_sigaction *,
60					struct sigaction *);
61static void bsd_to_ibcs2_sigaction(struct sigaction *,
62					struct ibcs2_sigaction *);
63
64int bsd_to_ibcs2_sig[IBCS2_SIGTBLSZ] = {
65	IBCS2_SIGHUP,		/* 1 */
66	IBCS2_SIGINT,		/* 2 */
67	IBCS2_SIGQUIT,		/* 3 */
68	IBCS2_SIGILL,		/* 4 */
69	IBCS2_SIGTRAP,		/* 5 */
70	IBCS2_SIGABRT,		/* 6 */
71	IBCS2_SIGEMT,		/* 7 */
72	IBCS2_SIGFPE,		/* 8 */
73	IBCS2_SIGKILL,		/* 9 */
74	IBCS2_SIGBUS,		/* 10 */
75	IBCS2_SIGSEGV,		/* 11 */
76	IBCS2_SIGSYS,		/* 12 */
77	IBCS2_SIGPIPE,		/* 13 */
78	IBCS2_SIGALRM,		/* 14 */
79	IBCS2_SIGTERM,		/* 15 */
80	0,			/* 16 - SIGURG */
81	IBCS2_SIGSTOP,		/* 17 */
82	IBCS2_SIGTSTP,		/* 18 */
83	IBCS2_SIGCONT,		/* 19 */
84	IBCS2_SIGCLD,		/* 20 */
85	IBCS2_SIGTTIN,		/* 21 */
86	IBCS2_SIGTTOU,		/* 22 */
87	IBCS2_SIGPOLL,		/* 23 */
88	0,			/* 24 - SIGXCPU */
89	0,			/* 25 - SIGXFSZ */
90	IBCS2_SIGVTALRM,	/* 26 */
91	IBCS2_SIGPROF,		/* 27 */
92	IBCS2_SIGWINCH,		/* 28 */
93	0,			/* 29 */
94	IBCS2_SIGUSR1,		/* 30 */
95	IBCS2_SIGUSR2,		/* 31 */
96	0			/* 32 */
97};
98
99static int ibcs2_to_bsd_sig[IBCS2_SIGTBLSZ] = {
100	SIGHUP,			/* 1 */
101	SIGINT,			/* 2 */
102	SIGQUIT,		/* 3 */
103	SIGILL,			/* 4 */
104	SIGTRAP,		/* 5 */
105	SIGABRT,		/* 6 */
106	SIGEMT,			/* 7 */
107	SIGFPE,			/* 8 */
108	SIGKILL,		/* 9 */
109	SIGBUS,			/* 10 */
110	SIGSEGV,		/* 11 */
111	SIGSYS,			/* 12 */
112	SIGPIPE,		/* 13 */
113	SIGALRM,		/* 14 */
114	SIGTERM,		/* 15 */
115	SIGUSR1,		/* 16 */
116	SIGUSR2,		/* 17 */
117	SIGCHLD,		/* 18 */
118	0,			/* 19 - SIGPWR */
119	SIGWINCH,		/* 20 */
120	0,			/* 21 */
121	SIGIO,			/* 22 */
122	SIGSTOP,		/* 23 */
123	SIGTSTP,		/* 24 */
124	SIGCONT,		/* 25 */
125	SIGTTIN,		/* 26 */
126	SIGTTOU,		/* 27 */
127	SIGVTALRM,		/* 28 */
128	SIGPROF,		/* 29 */
129	0,			/* 30 */
130	0,			/* 31 */
131	0			/* 32 */
132};
133
134void
135ibcs2_to_bsd_sigset(iss, bss)
136	const ibcs2_sigset_t *iss;
137	sigset_t *bss;
138{
139	int i, newsig;
140
141	sigemptyset(bss);
142	for (i = 1; i <= IBCS2_SIGTBLSZ; i++) {
143		if (ibcs2_sigismember(iss, i)) {
144			newsig = ibcs2_to_bsd_sig[_SIG_IDX(i)];
145			if (newsig)
146				sigaddset(bss, newsig);
147		}
148	}
149}
150
151static void
152bsd_to_ibcs2_sigset(bss, iss)
153	const sigset_t *bss;
154	ibcs2_sigset_t *iss;
155{
156	int i, newsig;
157
158	ibcs2_sigemptyset(iss);
159	for (i = 1; i <= IBCS2_SIGTBLSZ; i++) {
160		if (sigismember(bss, i)) {
161			newsig = bsd_to_ibcs2_sig[_SIG_IDX(i)];
162			if (newsig)
163				ibcs2_sigaddset(iss, newsig);
164		}
165	}
166}
167
168static void
169ibcs2_to_bsd_sigaction(isa, bsa)
170	struct ibcs2_sigaction *isa;
171	struct sigaction *bsa;
172{
173
174	bsa->sa_handler = isa->isa_handler;
175	ibcs2_to_bsd_sigset(&isa->isa_mask, &bsa->sa_mask);
176	bsa->sa_flags = 0;	/* ??? SA_NODEFER */
177	if ((isa->isa_flags & IBCS2_SA_NOCLDSTOP) != 0)
178		bsa->sa_flags |= SA_NOCLDSTOP;
179}
180
181static void
182bsd_to_ibcs2_sigaction(bsa, isa)
183	struct sigaction *bsa;
184	struct ibcs2_sigaction *isa;
185{
186
187	isa->isa_handler = bsa->sa_handler;
188	bsd_to_ibcs2_sigset(&bsa->sa_mask, &isa->isa_mask);
189	isa->isa_flags = 0;
190	if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
191		isa->isa_flags |= IBCS2_SA_NOCLDSTOP;
192}
193
194int
195ibcs2_sigaction(struct thread *td, struct ibcs2_sigaction_args *uap)
196{
197	struct ibcs2_sigaction isa;
198	struct sigaction nbsa, obsa;
199	struct sigaction *nbsap;
200 	int error;
201
202	if (uap->act != NULL) {
203		if ((error = copyin(uap->act, &isa, sizeof(isa))) != 0)
204			return (error);
205		ibcs2_to_bsd_sigaction(&isa, &nbsa);
206		nbsap = &nbsa;
207	} else
208		nbsap = NULL;
209	if (uap->sig <= 0 || uap->sig > IBCS2_NSIG)
210		return (EINVAL);
211	error = kern_sigaction(td, ibcs2_to_bsd_sig[_SIG_IDX(uap->sig)], &nbsa,
212	    &obsa, 0);
213	if (error == 0 && uap->oact != NULL) {
214		bsd_to_ibcs2_sigaction(&obsa, &isa);
215		error = copyout(&isa, uap->oact, sizeof(isa));
216	}
217	return (error);
218}
219
220int
221ibcs2_sigsys(struct thread *td, struct ibcs2_sigsys_args *uap)
222{
223	struct proc *p = td->td_proc;
224	struct sigaction sa;
225	int signum = IBCS2_SIGNO(uap->sig);
226	int error;
227
228	if (signum <= 0 || signum > IBCS2_NSIG) {
229		if (IBCS2_SIGCALL(uap->sig) == IBCS2_SIGNAL_MASK ||
230		    IBCS2_SIGCALL(uap->sig) == IBCS2_SIGSET_MASK)
231			td->td_retval[0] = (int)IBCS2_SIG_ERR;
232		return EINVAL;
233	}
234	signum = ibcs2_to_bsd_sig[_SIG_IDX(signum)];
235
236	switch (IBCS2_SIGCALL(uap->sig)) {
237	case IBCS2_SIGSET_MASK:
238		/*
239		 * Check for SIG_HOLD action.
240		 * Otherwise, perform signal() except with different sa_flags.
241		 */
242		if (uap->fp != IBCS2_SIG_HOLD) {
243			/* add sig to mask before exececuting signal handler */
244			sa.sa_flags = 0;
245			goto ibcs2_sigset;
246		}
247		/* else FALLTHROUGH to sighold */
248
249	case IBCS2_SIGHOLD_MASK:
250		{
251			sigset_t mask;
252
253			SIGEMPTYSET(mask);
254			SIGADDSET(mask, signum);
255			return (kern_sigprocmask(td, SIG_BLOCK, &mask, NULL,
256				    0));
257		}
258
259	case IBCS2_SIGNAL_MASK:
260		{
261			struct sigaction osa;
262
263			/* do not automatically block signal */
264			sa.sa_flags = SA_NODEFER;
265#ifdef SA_RESETHAND
266			if((signum != IBCS2_SIGILL) &&
267			   (signum != IBCS2_SIGTRAP) &&
268			   (signum != IBCS2_SIGPWR))
269				/* set to SIG_DFL before executing handler */
270				sa.sa_flags |= SA_RESETHAND;
271#endif
272		ibcs2_sigset:
273			sa.sa_handler = uap->fp;
274			sigemptyset(&sa.sa_mask);
275#if 0
276			if (signum != SIGALRM)
277				sa.sa_flags |= SA_RESTART;
278#endif
279			error = kern_sigaction(td, signum, &sa, &osa, 0);
280			if (error != 0) {
281				DPRINTF(("signal: sigaction failed: %d\n",
282					 error));
283				td->td_retval[0] = (int)IBCS2_SIG_ERR;
284				return (error);
285			}
286			td->td_retval[0] = (int)osa.sa_handler;
287
288			/* special sigset() check */
289                        if(IBCS2_SIGCALL(uap->sig) == IBCS2_SIGSET_MASK) {
290				PROC_LOCK(p);
291			        /* check to make sure signal is not blocked */
292                                if(sigismember(&td->td_sigmask, signum)) {
293				        /* return SIG_HOLD and unblock signal*/
294                                        td->td_retval[0] = (int)IBCS2_SIG_HOLD;
295					SIGDELSET(td->td_sigmask, signum);
296					signotify(td);
297				}
298				PROC_UNLOCK(p);
299			}
300
301			return 0;
302		}
303
304	case IBCS2_SIGRELSE_MASK:
305		{
306			sigset_t mask;
307
308			SIGEMPTYSET(mask);
309			SIGADDSET(mask, signum);
310			return (kern_sigprocmask(td, SIG_UNBLOCK, &mask, NULL,
311				    0));
312		}
313
314	case IBCS2_SIGIGNORE_MASK:
315		{
316			sa.sa_handler = SIG_IGN;
317			sigemptyset(&sa.sa_mask);
318			sa.sa_flags = 0;
319			error = kern_sigaction(td, signum, &sa, NULL, 0);
320			if (error != 0)
321				DPRINTF(("sigignore: sigaction failed\n"));
322			return (error);
323		}
324
325	case IBCS2_SIGPAUSE_MASK:
326		{
327			sigset_t mask;
328
329			PROC_LOCK(p);
330			mask = td->td_sigmask;
331			PROC_UNLOCK(p);
332			SIGDELSET(mask, signum);
333			return kern_sigsuspend(td, mask);
334		}
335
336	default:
337		return ENOSYS;
338	}
339}
340
341int
342ibcs2_sigprocmask(struct thread *td, struct ibcs2_sigprocmask_args *uap)
343{
344	ibcs2_sigset_t iss;
345	sigset_t oss, nss;
346	sigset_t *nssp;
347	int error, how;
348
349	switch (uap->how) {
350	case IBCS2_SIG_BLOCK:
351		how = SIG_BLOCK;
352		break;
353	case IBCS2_SIG_UNBLOCK:
354		how = SIG_UNBLOCK;
355		break;
356	case IBCS2_SIG_SETMASK:
357		how = SIG_SETMASK;
358		break;
359	default:
360		return (EINVAL);
361	}
362	if (uap->set != NULL) {
363		if ((error = copyin(uap->set, &iss, sizeof(iss))) != 0)
364			return error;
365		ibcs2_to_bsd_sigset(&iss, &nss);
366		nssp = &nss;
367	} else
368		nssp = NULL;
369	error = kern_sigprocmask(td, how, nssp, &oss, 0);
370	if (error == 0 && uap->oset != NULL) {
371		bsd_to_ibcs2_sigset(&oss, &iss);
372		error = copyout(&iss, uap->oset, sizeof(iss));
373	}
374	return (error);
375}
376
377int
378ibcs2_sigpending(struct thread *td, struct ibcs2_sigpending_args *uap)
379{
380	struct proc *p = td->td_proc;
381	sigset_t bss;
382	ibcs2_sigset_t iss;
383
384	PROC_LOCK(p);
385	bss = td->td_siglist;
386	SIGSETOR(bss, p->p_siglist);
387	SIGSETAND(bss, td->td_sigmask);
388	PROC_UNLOCK(p);
389	bsd_to_ibcs2_sigset(&bss, &iss);
390
391	return copyout(&iss, uap->mask, sizeof(iss));
392}
393
394int
395ibcs2_sigsuspend(struct thread *td, struct ibcs2_sigsuspend_args *uap)
396{
397	ibcs2_sigset_t sss;
398	sigset_t bss;
399	int error;
400
401	if ((error = copyin(uap->mask, &sss, sizeof(sss))) != 0)
402		return error;
403
404	ibcs2_to_bsd_sigset(&sss, &bss);
405	return kern_sigsuspend(td, bss);
406}
407
408int
409ibcs2_pause(struct thread *td, struct ibcs2_pause_args *uap)
410{
411	sigset_t mask;
412
413	PROC_LOCK(td->td_proc);
414	mask = td->td_sigmask;
415	PROC_UNLOCK(td->td_proc);
416	return kern_sigsuspend(td, mask);
417}
418
419int
420ibcs2_kill(struct thread *td, struct ibcs2_kill_args *uap)
421{
422	struct kill_args ka;
423
424	if (uap->signo <= 0 || uap->signo > IBCS2_NSIG)
425		return (EINVAL);
426	ka.pid = uap->pid;
427	ka.signum = ibcs2_to_bsd_sig[_SIG_IDX(uap->signo)];
428	return sys_kill(td, &ka);
429}
430