xref: /illumos-gate/usr/src/lib/brand/solaris10/s10_brand/common/s10_signal.c (revision 4e567b4443d7a1680a7319275e5288eef2c92319)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <sys/types.h>
28 #include <sys/brand.h>
29 #include <sys/errno.h>
30 #include <sys/sysconfig.h>
31 #include <sys/ucontext.h>
32 #include <sys/wait.h>
33 #include <stdlib.h>
34 #include <strings.h>
35 #include <signal.h>
36 
37 #include <s10_brand.h>
38 #include <s10_misc.h>
39 #include <s10_signal.h>
40 
41 s10_sighandler_t s10_handlers[S10_NSIG - 1];
42 
43 /*
44  * Theory of operation:
45  *
46  * As of now, Solaris 10 and solaris_nevada signal numbers match all the
47  * way through SIGJVM2 (1 - 40) and the first 8 realtime signals (41 - 48).
48  * However, solaris_nevada provides 32 realtime signals rather than 8 for S10.
49  *
50  * We do not assume that the current range of realtime signals is
51  * _SIGRTMIN - _SIGRTMAX.  As a hedge against future changes,
52  * we obtain the realtime signal range via SIGRTMIN and SIGRTMAX.
53  *
54  * Therefore, we must interpose on the various signal calls to translate
55  * signal masks and signal handlers that deal with SIGRTMIN - SIGRTMAX to
56  * refer to a potentially different range and to intercenpt any "illegal"
57  * signals that might otherwise be sent to an S10 process.
58  *
59  * Important exception:
60  * We cannot interpose on the SYS_context system call in order to deal with the
61  * sigset_t contained within the ucontext_t structure because the getcontext()
62  * part of this system call trap would then return an incorrect set of machine
63  * registers.  See the getcontext() functions in libc to get the gory details.
64  * The kernel code for getcontext() and setcontext() has been made brand-aware
65  * in order to deal with this.
66  *
67  * Simple translation is all that is required to handle most system calls,
68  * but signal handlers also must be interposed upon so that a user signal
69  * handler sees proper signal numbers in its arguments, any passed siginfo_t
70  * and in the signal mask reported in its ucontext_t.
71  *
72  * libc adds its own signal handler to handled signals such that the
73  * signal delivery mechanism looks like:
74  *
75  * signal ->
76  *     libc sigacthandler() ->
77  *         user signal handler()
78  *
79  * With interposition, this will instead look like:
80  *
81  * signal ->
82  *     s10_sigacthandler() ->
83  *         libc sigacthandler() ->
84  *             user signal handler()
85  */
86 
87 /*
88  * A little exposition on SIGRTMIN and SIGRTMAX:
89  *
90  * For configurability reasons, in Solaris SIGRTMIN and SIGRTMAX are actually
91  * #defined to be routines:
92  *
93  *    #define SIGRTMIN ((int)_sysconf(_SC_SIGRT_MIN))
94  *    #define SIGRTMAX ((int)_sysconf(_SC_SIGRT_MAX))
95  *
96  * This means we need routines that will call the native sysconfig() system
97  * call to find out what the native values for SIGRTMIN and SIGRTMAX are, and
98  * those are native_sigrtmin() and native_sigrtmax(), respectively.
99  *
100  * To try and mitigate confusion this might cause, rather than use SIGRTMIN and
101  * SIGRTMAX directly, mnemonic convenience macros are #defined to clarify the
102  * matter:
103  *
104  *     S10_SIGRTMIN
105  *     S10_SIGRTMAX
106  *     NATIVE_SIGRTMIN
107  *     NATIVE_SIGRTMAX
108  */
109 
110 static int
111 native_sigrtmin()
112 {
113 	static int sigrtmin;
114 	sysret_t rval;
115 
116 	if (sigrtmin)
117 		return (sigrtmin);
118 	sigrtmin = __systemcall(&rval, SYS_sysconfig + 1024, _CONFIG_SIGRT_MIN)?
119 	    _SIGRTMIN : (int)rval.sys_rval1;
120 	return (sigrtmin);
121 }
122 
123 static int
124 native_sigrtmax()
125 {
126 	static int sigrtmax;
127 	sysret_t rval;
128 
129 	if (sigrtmax)
130 		return (sigrtmax);
131 	sigrtmax = __systemcall(&rval, SYS_sysconfig + 1024, _CONFIG_SIGRT_MAX)?
132 	    _SIGRTMAX : (int)rval.sys_rval1;
133 	return (sigrtmax);
134 }
135 
136 #define	NATIVE_SIGRTMIN		(native_sigrtmin())
137 #define	NATIVE_SIGRTMAX		(native_sigrtmax())
138 
139 /*
140  * These #defines are setup to create the SIGADDSET and SIGISMEMBER macros,
141  * needed because the sigaddset(3C) and sigismember(3C) calls make function
142  * calls that end up being recursive in an interpositioned system call
143  * environment.
144  */
145 #define	MAXBITNO	(NBPW*8)
146 #define	SIGWORD(n)	((n-1)/MAXBITNO)
147 #define	BITMASK(n)	(1L<<((n-1)%MAXBITNO))
148 
149 #define	SIGADDSET(sigset, sig) \
150 	((sigset)->__sigbits[SIGWORD(sig)] |= BITMASK(sig))
151 
152 #define	SIGISMEMBER(sigset, sig) \
153 	(((sigset)->__sigbits[SIGWORD(sig)] & BITMASK(sig)) != 0)
154 
155 /*
156  * Convert an S10 signal number to its native value.
157  */
158 static int
159 s10sig_to_native(int sig)
160 {
161 	/* signals 1 .. SIGJVM2 are the same between S10 and native */
162 	if (sig <= SIGJVM2)
163 		return (sig);
164 
165 	/*
166 	 * If a signal is > SIGJVM2 but is < S10_SIGRTMIN, it's being used
167 	 * for some private purpose we likely wouldn't emulate properly.
168 	 */
169 	if (sig < S10_SIGRTMIN)		/* can't happen */
170 		return (-1);
171 
172 	/*
173 	 * Map S10 RT signals to their native counterparts to the degree
174 	 * possible.  If the signal would be out of the native RT signal
175 	 * range, return an error to the caller.
176 	 */
177 	sig -= S10_SIGRTMIN;
178 
179 	if (sig > (NATIVE_SIGRTMAX - NATIVE_SIGRTMIN))
180 		return (-1);
181 
182 	return (NATIVE_SIGRTMIN + sig);
183 }
184 
185 /*
186  * Convert an S10 sigset_t to its native version.
187  */
188 int
189 s10sigset_to_native(const sigset_t *s10_set, sigset_t *native_set)
190 {
191 	int sig;
192 	int nativesig;
193 	sigset_t srcset, newset;
194 
195 	if (s10_uucopy(s10_set, &srcset, sizeof (sigset_t)) != 0)
196 		return (EFAULT);
197 
198 	(void) sigemptyset(&newset);
199 
200 	/*
201 	 * Shortcut: we know the first 32 signals are the same in both
202 	 * s10 and native Solaris.  Just assign the first word.
203 	 */
204 	newset.__sigbits[0] = srcset.__sigbits[0];
205 
206 	/*
207 	 * Copy the remainder of the initial set of common signals.
208 	 */
209 	for (sig = 33; sig <= SIGJVM2; sig++)
210 		if (SIGISMEMBER(&srcset, sig))
211 			SIGADDSET(&newset, sig);
212 
213 	/* convert any S10 RT signals to their native equivalents */
214 	for (sig = S10_SIGRTMIN; sig <= S10_SIGRTMAX; sig++) {
215 		if (SIGISMEMBER(&srcset, sig) &&
216 		    (nativesig = s10sig_to_native(sig)) > 0)
217 			SIGADDSET(&newset, nativesig);
218 	}
219 
220 	if (s10_uucopy(&newset, native_set, sizeof (sigset_t)) != 0)
221 		return (EFAULT);
222 
223 	return (0);
224 }
225 
226 /*
227  * Convert a native signal number to its S10 value.
228  */
229 int
230 nativesig_to_s10(int sig)
231 {
232 	/* signals 1 .. SIGJVM2 are the same between native and S10 */
233 	if (sig <= SIGJVM2)
234 		return (sig);
235 
236 	/*
237 	 * We have no way to emulate native signals between (SIGJVM2 + 1) and
238 	 * NATIVE_SIGRTMIN, so return an error to the caller.
239 	 */
240 	if (sig < NATIVE_SIGRTMIN)	/* can't happen */
241 		return (-1);
242 
243 	/*
244 	 * Map native RT signals to their S10 counterparts to the degree
245 	 * possible.  If the signal would be out of range for S10, return
246 	 * an error to the caller.
247 	 */
248 	sig -= NATIVE_SIGRTMIN;
249 
250 	if (sig > (S10_SIGRTMAX - S10_SIGRTMIN))
251 		return (-1);
252 
253 	return (S10_SIGRTMIN + sig);
254 }
255 
256 /*
257  * Convert a native sigset_t to its S10 version.
258  */
259 int
260 nativesigset_to_s10(const sigset_t *native_set, sigset_t *s10_set)
261 {
262 	int sig;
263 	int s10sig;
264 	sigset_t srcset, newset;
265 
266 	if (s10_uucopy(native_set, &srcset, sizeof (sigset_t)) != 0)
267 		return (EFAULT);
268 
269 	(void) sigemptyset(&newset);
270 
271 	/*
272 	 * Shortcut: we know the first 32 signals are the same in both
273 	 * s10 and native Solaris.  Just assign the first word.
274 	 */
275 	newset.__sigbits[0] = srcset.__sigbits[0];
276 
277 	/*
278 	 * Copy the remainder of the initial set of common signals.
279 	 */
280 	for (sig = 33; sig <= SIGJVM2; sig++)
281 		if (SIGISMEMBER(&srcset, sig))
282 			SIGADDSET(&newset, sig);
283 
284 	/* convert any RT signals to their S10 values */
285 	for (sig = NATIVE_SIGRTMIN; sig <= NATIVE_SIGRTMAX; sig++) {
286 		if (SIGISMEMBER(&srcset, sig) &&
287 		    (s10sig = nativesig_to_s10(sig)) > 0)
288 			SIGADDSET(&newset, s10sig);
289 	}
290 
291 	if (s10_uucopy(&newset, s10_set, sizeof (sigset_t)) != 0)
292 		return (EFAULT);
293 
294 	return (0);
295 }
296 
297 /*
298  * This is our interposed signal handler.
299  * Fix up the arguments received from the kernel and jump
300  * to the s10 signal handler, normally libc's sigacthandler().
301  */
302 static void
303 s10_sigacthandler(int sig, siginfo_t *sip, void *uvp)
304 {
305 	int s10_sig;
306 	ucontext_t *ucp;
307 
308 	s10_sig = nativesig_to_s10(sig);
309 	if (s10_sig <= 0)	/* can't happen? */
310 		s10_abort(sig, "Received an impossible signal");
311 	if (sip != NULL) {
312 		/*
313 		 * All we really have to do is map the signal number,
314 		 * which changes only for the realtime signals,
315 		 * so all the rest of the siginfo structure is the
316 		 * same between s10 and native.
317 		 */
318 		if (sip->si_signo != sig)	/* can't happen? */
319 			s10_abort(sig, "Received an impossible siginfo");
320 		sip->si_signo = s10_sig;
321 	}
322 	if ((ucp = uvp) != NULL &&
323 	    (ucp->uc_flags & UC_SIGMASK))
324 		(void) nativesigset_to_s10(&ucp->uc_sigmask, &ucp->uc_sigmask);
325 
326 	s10_handlers[s10_sig - 1](s10_sig, sip, uvp);
327 }
328 
329 /*
330  * Interposition upon SYS_lwp_sigmask
331  */
332 int
333 s10_lwp_sigmask(sysret_t *rval, int how, uint_t bits0, uint_t bits1)
334 {
335 	sigset_t s10_blockset;
336 	sigset_t native_blockset;
337 	int err;
338 
339 	s10_blockset.__sigbits[0] = bits0;
340 	s10_blockset.__sigbits[1] = bits1;
341 	s10_blockset.__sigbits[2] = 0;
342 	s10_blockset.__sigbits[3] = 0;
343 
344 	(void) s10sigset_to_native(&s10_blockset, &native_blockset);
345 
346 	err = __systemcall(rval, SYS_lwp_sigmask + 1024,
347 	    how,
348 	    native_blockset.__sigbits[0],
349 	    native_blockset.__sigbits[1],
350 	    native_blockset.__sigbits[2],
351 	    native_blockset.__sigbits[3]);
352 
353 	if (err != 0)
354 		return (err);
355 
356 	native_blockset.__sigbits[0] = (int)rval->sys_rval1;
357 	native_blockset.__sigbits[1] = (int)rval->sys_rval2;
358 	native_blockset.__sigbits[2] = 0;
359 	native_blockset.__sigbits[3] = 0;
360 
361 	(void) nativesigset_to_s10(&native_blockset, &s10_blockset);
362 
363 	rval->sys_rval1 = s10_blockset.__sigbits[0];
364 	rval->sys_rval2 = s10_blockset.__sigbits[1];
365 
366 	return (0);
367 }
368 
369 /*
370  * Interposition upon SYS_sigprocmask
371  */
372 int
373 s10_sigprocmask(sysret_t *rval, int how, const sigset_t *set, sigset_t *oset)
374 {
375 	sigset_t sigset_set, sigset_oset;
376 	sigset_t *set_ptr, *oset_ptr;
377 	int err;
378 
379 	oset_ptr = (oset == NULL) ? NULL : &sigset_oset;
380 	set_ptr = (set == NULL) ? NULL : &sigset_set;
381 
382 	if (set_ptr != NULL &&
383 	    (err = s10sigset_to_native(set, set_ptr)) != 0)
384 		return (err);
385 
386 	if ((err = __systemcall(rval, SYS_sigprocmask + 1024,
387 	    how, set_ptr, oset_ptr)) != 0)
388 		return (err);
389 
390 	if (oset_ptr != NULL &&
391 	    (err = nativesigset_to_s10(oset_ptr, oset)) != 0)
392 		return (err);
393 
394 	return (0);
395 }
396 
397 /*
398  * Interposition upon SYS_sigsuspend
399  */
400 int
401 s10_sigsuspend(sysret_t *rval, const sigset_t *set)
402 {
403 	sigset_t sigset_set;
404 	int err;
405 
406 	if ((err = s10sigset_to_native(set, &sigset_set)) != 0) {
407 		(void) S10_TRUSS_POINT_1(rval, SYS_sigsuspend, err, set);
408 		return (err);
409 	}
410 
411 	return (__systemcall(rval, SYS_sigsuspend + 1024, &sigset_set));
412 }
413 
414 /*
415  * Interposition upon SYS_sigaction
416  *
417  * There is a fair amount of complexity here due to the need to interpose
418  * on any registered user signal handler.
419  *
420  * The idea is that if a user signal handler is installed, we must install
421  * our own signal handler between the system and the signal handler being
422  * registered.  If the signal handler to be registered is SIG_DFL or SIG_IGN,
423  * we should remove our interpositioned handler as it's no longer needed.
424  *
425  * The way we do this is we set the signal handler to call s10_sigacthandler(),
426  * and then store the address of the passed signal handler in a global
427  * per-process array, s10_handlers[].
428  *
429  * We rely on the fact that the s10 libc blocks all signals during
430  * its call to the sigaction() system call to guarantee atomicity.
431  */
432 int
433 s10_sigaction(sysret_t *rval,
434     int sig, const struct sigaction *act, struct sigaction *oact)
435 {
436 	struct sigaction sigact, osigact;
437 	struct sigaction *sigactp, *osigactp;
438 	int err, nativesig;
439 	void (*handler)();
440 
441 	if ((nativesig = s10sig_to_native(sig)) < 0) {
442 		(void) S10_TRUSS_POINT_3(rval, SYS_sigaction, EINVAL,
443 		    sig, act, oact);
444 		return (EINVAL);
445 	}
446 
447 	if (act == NULL) {
448 		sigactp = NULL;
449 	} else {
450 		sigactp = &sigact;
451 
452 		if (s10_uucopy(act, sigactp, sizeof (struct sigaction)) != 0)
453 			return (EFAULT);
454 
455 		if ((err = s10sigset_to_native(&sigactp->sa_mask,
456 		    &sigactp->sa_mask)) != 0) {
457 			(void) S10_TRUSS_POINT_3(rval, SYS_sigaction, err,
458 			    sig, act, oact);
459 			return (err);
460 		}
461 	}
462 
463 	osigactp = ((oact == NULL) ? NULL : &osigact);
464 
465 	if (sigactp != NULL) {
466 		handler = sigactp->sa_handler;
467 		if (handler != SIG_DFL && handler != SIG_IGN)
468 			sigactp->sa_handler = s10_sigacthandler;
469 	}
470 
471 	if ((err = __systemcall(rval, SYS_sigaction + 1024,
472 	    nativesig, sigactp, osigactp)) != 0)
473 		return (err);
474 
475 	/*
476 	 * Translate the old signal mask if we are supposed to return the old
477 	 * struct sigaction.
478 	 *
479 	 * Note that we may have set the signal handler, but may return EFAULT
480 	 * here if the oact parameter is bad.
481 	 *
482 	 * That's OK, because the direct system call acts the same way.
483 	 */
484 	if (osigactp != NULL) {
485 		err = nativesigset_to_s10(&osigactp->sa_mask,
486 		    &osigactp->sa_mask);
487 
488 		if (osigactp->sa_handler == s10_sigacthandler)
489 			osigactp->sa_handler = s10_handlers[sig - 1];
490 
491 		if (err == 0 &&
492 		    s10_uucopy(osigactp, oact, sizeof (struct sigaction)) != 0)
493 			err = EFAULT;
494 	}
495 
496 	/*
497 	 * Do not store SIG_DFL or SIG_IGN into the array of remembered
498 	 * signal handlers.  Only store bona-fide function addresses.
499 	 * This is to avoid a race condition in which some thread
500 	 * sets the signal handler to SIG_DFL or SIG_IGN while some
501 	 * other thread is fielding the signal but has not yet reached
502 	 * s10_sigacthandler().  s10_sigacthandler() will unconditionally
503 	 * call the remembered signal handler and it it calls SIG_DFL or
504 	 * SIG_IGN, the process will incur a SIGSEGV or SIGBUS signal.
505 	 * This also allows a vfork() child to set signal handlers
506 	 * to SIG_DFL or SIG_IGN without corrupting the parent's
507 	 * address space.
508 	 */
509 	if (sigactp != NULL &&
510 	    handler != SIG_DFL && handler != SIG_IGN)
511 		s10_handlers[sig - 1] = handler;
512 
513 	return (err);
514 }
515 
516 /*
517  * Interposition upon SYS_sigpending
518  */
519 int
520 s10_sigpending(sysret_t *rval, int flag, sigset_t *set)
521 {
522 	sigset_t sigset_set;
523 	int err;
524 
525 	if ((err = __systemcall(rval, SYS_sigpending + 1024,
526 	    flag, &sigset_set)) != 0)
527 		return (err);
528 
529 	if ((err = nativesigset_to_s10(&sigset_set, set)) != 0)
530 		return (err);
531 
532 	return (0);
533 }
534 
535 /*
536  * Interposition upon SYS_sigsendsys
537  */
538 int
539 s10_sigsendsys(sysret_t *rval, procset_t *psp, int sig)
540 {
541 	int nativesig;
542 
543 	if ((nativesig = s10sig_to_native(sig)) < 0) {
544 		(void) S10_TRUSS_POINT_2(rval, SYS_sigsendsys, EINVAL,
545 		    psp, sig);
546 		return (EINVAL);
547 	}
548 
549 	return (__systemcall(rval, SYS_sigsendsys + 1024, psp, nativesig));
550 }
551 
552 /*
553  * Convert the siginfo_t code and status fields to an old style
554  * wait status for s10_wait(), below.
555  */
556 static int
557 wstat(int code, int status)
558 {
559 	int stat = (status & 0377);
560 
561 	switch (code) {
562 	case CLD_EXITED:
563 		stat <<= 8;
564 		break;
565 	case CLD_DUMPED:
566 		stat |= WCOREFLG;
567 		break;
568 	case CLD_KILLED:
569 		break;
570 	case CLD_TRAPPED:
571 	case CLD_STOPPED:
572 		stat <<= 8;
573 		stat |= WSTOPFLG;
574 		break;
575 	case CLD_CONTINUED:
576 		stat = WCONTFLG;
577 		break;
578 	}
579 	return (stat);
580 }
581 
582 /*
583  * Interposition upon SYS_wait
584  */
585 int
586 s10_wait(sysret_t *rval)
587 {
588 	int err;
589 	siginfo_t info;
590 
591 	err = s10_waitid(rval, P_ALL, 0, &info, WEXITED | WTRAPPED);
592 	if (err != 0)
593 		return (err);
594 
595 	rval->sys_rval1 = info.si_pid;
596 	rval->sys_rval2 = wstat(info.si_code, info.si_status);
597 
598 	return (0);
599 }
600 
601 /*
602  * Interposition upon SYS_waitid
603  */
604 int
605 s10_waitid(sysret_t *rval,
606     idtype_t idtype, id_t id, siginfo_t *infop, int options)
607 {
608 	int err, sig;
609 
610 	err = __systemcall(rval, SYS_waitid + 1024, idtype, id, infop, options);
611 	if (err != 0)
612 		return (err);
613 
614 	/*
615 	 * If the process being waited for terminated or stopped due to a
616 	 * signal, translate the signal number from its native value to its
617 	 * S10 equivalent.
618 	 *
619 	 * If we can't legally translate the signal number, just sort of punt
620 	 * and leave it untranslated.
621 	 *
622 	 * We shouldn't return EINVAL as the syscall didn't technically fail.
623 	 */
624 	if (infop->si_signo == SIGCLD && infop->si_code != CLD_EXITED &&
625 	    (sig = nativesig_to_s10(infop->si_status)) > 0)
626 		infop->si_status = sig;
627 
628 	return (0);
629 }
630 
631 /*
632  * Interposition upon SYS_sigtimedwait
633  */
634 int
635 s10_sigtimedwait(sysret_t *rval,
636     const sigset_t *set, siginfo_t *info, const timespec_t *timeout)
637 {
638 	sigset_t sigset_set;
639 	int err, sig;
640 
641 	if ((err = s10sigset_to_native(set, &sigset_set)) != 0) {
642 		(void) S10_TRUSS_POINT_3(rval, SYS_sigtimedwait, err,
643 		    set, info, timeout);
644 		return (err);
645 	}
646 
647 	if ((err = __systemcall(rval, SYS_sigtimedwait + 1024,
648 	    &sigset_set, info, timeout)) != 0)
649 		return (err);
650 
651 	if (info != NULL) {
652 		/*
653 		 * If we can't legally translate the signal number in the
654 		 * siginfo_t, just sort of punt and leave it untranslated.
655 		 *
656 		 * We shouldn't return EINVAL as the syscall didn't technically
657 		 * fail.
658 		 */
659 		if ((sig = nativesig_to_s10(info->si_signo)) > 0)
660 			info->si_signo = sig;
661 	}
662 
663 	/*
664 	 * If we can't legally translate the signal number returned by the
665 	 * sigtimedwait syscall, just sort of punt and leave it untranslated.
666 	 *
667 	 * We shouldn't return EINVAL as the syscall didn't technically
668 	 * fail.
669 	 */
670 	if ((sig = nativesig_to_s10((int)rval->sys_rval1)) > 0)
671 		rval->sys_rval1 = sig;
672 
673 	return (0);
674 }
675 
676 /*
677  * Interposition upon SYS_sigqueue
678  */
679 int
680 s10_sigqueue(sysret_t *rval, pid_t pid, int signo, void *value, int si_code)
681 {
682 	int nativesig;
683 
684 	if ((nativesig = s10sig_to_native(signo)) < 0) {
685 		(void) S10_TRUSS_POINT_4(rval, SYS_sigqueue, EINVAL,
686 		    pid, signo, value, si_code);
687 		return (EINVAL);
688 	}
689 
690 	if (pid == 1)
691 		pid = zone_init_pid;
692 
693 	/*
694 	 * The native version of this syscall takes an extra argument.
695 	 * The new last arg "block" flag should be zero.  The block flag
696 	 * is used by the Opensolaris AIO implementation, which is now
697 	 * part of libc.
698 	 */
699 	return (__systemcall(rval, SYS_sigqueue + 1024,
700 	    pid, nativesig, value, si_code, 0));
701 }
702 
703 /*
704  * Interposition upon SYS_signotify
705  */
706 int
707 s10_signotify(sysret_t *rval,
708     int cmd, siginfo_t *siginfo, signotify_id_t *sn_id)
709 {
710 	siginfo_t *infop, info;
711 
712 	infop = siginfo;
713 
714 	/* only check for a valid siginfo pointer in the case of SN_PROC */
715 	if (cmd == SN_PROC) {
716 		int nativesig;
717 
718 		if (s10_uucopy(infop, &info, sizeof (siginfo_t)) != 0)
719 			return (EFAULT);
720 
721 		if ((nativesig = s10sig_to_native(info.si_signo)) < 0) {
722 			(void) S10_TRUSS_POINT_3(rval, SYS_signotify, EINVAL,
723 			    cmd, siginfo, sn_id);
724 			return (EINVAL);
725 		}
726 
727 		info.si_signo = nativesig;
728 		infop = &info;
729 	}
730 
731 	return (__systemcall(rval, SYS_signotify + 1024, cmd, infop, sn_id));
732 }
733 
734 /*
735  * Interposition upon SYS_kill
736  */
737 int
738 s10_kill(sysret_t *rval, pid_t pid, int sig)
739 {
740 	int nativesig;
741 
742 	if ((nativesig = s10sig_to_native(sig)) < 0) {
743 		(void) S10_TRUSS_POINT_2(rval, SYS_kill, EINVAL, pid, sig);
744 		return (EINVAL);
745 	}
746 
747 	if (pid == 1)
748 		pid = zone_init_pid;
749 
750 	return (__systemcall(rval, SYS_kill + 1024, pid, nativesig));
751 }
752 
753 /*
754  * Interposition upon SYS_lwp_create
755  *
756  * See also the s10_lwp_create_correct_fs() function in s10_brand.c
757  * for the special case of creating an lwp in a 64-bit x86 process.
758  */
759 int
760 s10_lwp_create(sysret_t *rval, ucontext_t *ucp, int flags, id_t *new_lwp)
761 {
762 	ucontext_t s10_uc;
763 
764 	if (s10_uucopy(ucp, &s10_uc, sizeof (ucontext_t)) != 0)
765 		return (EFAULT);
766 
767 	if (s10_uc.uc_flags & UC_SIGMASK)
768 		(void) s10sigset_to_native(&s10_uc.uc_sigmask,
769 		    &s10_uc.uc_sigmask);
770 
771 	return (__systemcall(rval, SYS_lwp_create + 1024,
772 	    &s10_uc, flags, new_lwp));
773 }
774 
775 /*
776  * Interposition upon SYS_lwp_kill
777  */
778 int
779 s10_lwp_kill(sysret_t *rval, id_t lwpid, int sig)
780 {
781 	int nativesig;
782 
783 	if ((nativesig = s10sig_to_native(sig)) < 0) {
784 		(void) S10_TRUSS_POINT_2(rval, SYS_lwp_kill, EINVAL,
785 		    lwpid, sig);
786 		return (EINVAL);
787 	}
788 
789 	return (__systemcall(rval, SYS_lwp_kill + 1024, lwpid, nativesig));
790 }
791