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