xref: /titanic_51/usr/src/lib/brand/solaris10/s10_brand/common/s10_signal.c (revision 602423772f52c941d73a9f5aa3ea7249711300fb)
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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 #include <sys/types.h>
27 #include <sys/brand.h>
28 #include <sys/errno.h>
29 #include <sys/sysconfig.h>
30 #include <sys/ucontext.h>
31 #include <sys/wait.h>
32 #include <stdlib.h>
33 #include <strings.h>
34 #include <signal.h>
35 
36 #include <s10_brand.h>
37 #include <brand_misc.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 	 * If an app passes in a signal that is out of range, it
174 	 * expects to get back EINVAL.
175 	 */
176 	if (sig > S10_MAXSIG)
177 		return (-1);
178 
179 	/*
180 	 * Map S10 RT signals to their native counterparts to the degree
181 	 * possible.  If the signal would be out of the native RT signal
182 	 * range, return an error to the caller.
183 	 */
184 	sig -= S10_SIGRTMIN;
185 
186 	if (sig > (NATIVE_SIGRTMAX - NATIVE_SIGRTMIN))
187 		return (-1);
188 
189 	return (NATIVE_SIGRTMIN + sig);
190 }
191 
192 /*
193  * Convert an S10 sigset_t to its native version.
194  */
195 int
196 s10sigset_to_native(const sigset_t *s10_set, sigset_t *native_set)
197 {
198 	int sig;
199 	int nativesig;
200 	sigset_t srcset, newset;
201 
202 	if (brand_uucopy(s10_set, &srcset, sizeof (sigset_t)) != 0)
203 		return (EFAULT);
204 
205 	(void) sigemptyset(&newset);
206 
207 	/*
208 	 * Shortcut: we know the first 32 signals are the same in both
209 	 * s10 and native Solaris.  Just assign the first word.
210 	 */
211 	newset.__sigbits[0] = srcset.__sigbits[0];
212 
213 	/*
214 	 * Copy the remainder of the initial set of common signals.
215 	 */
216 	for (sig = 33; sig <= SIGJVM2; sig++)
217 		if (SIGISMEMBER(&srcset, sig))
218 			SIGADDSET(&newset, sig);
219 
220 	/* convert any S10 RT signals to their native equivalents */
221 	for (sig = S10_SIGRTMIN; sig <= S10_SIGRTMAX; sig++) {
222 		if (SIGISMEMBER(&srcset, sig) &&
223 		    (nativesig = s10sig_to_native(sig)) > 0)
224 			SIGADDSET(&newset, nativesig);
225 	}
226 
227 	if (brand_uucopy(&newset, native_set, sizeof (sigset_t)) != 0)
228 		return (EFAULT);
229 
230 	return (0);
231 }
232 
233 /*
234  * Convert a native signal number to its S10 value.
235  */
236 int
237 nativesig_to_s10(int sig)
238 {
239 	/* signals 1 .. SIGJVM2 are the same between native and S10 */
240 	if (sig <= SIGJVM2)
241 		return (sig);
242 
243 	/*
244 	 * We have no way to emulate native signals between (SIGJVM2 + 1) and
245 	 * NATIVE_SIGRTMIN, so return an error to the caller.
246 	 */
247 	if (sig < NATIVE_SIGRTMIN)	/* can't happen */
248 		return (-1);
249 
250 	/*
251 	 * Map native RT signals to their S10 counterparts to the degree
252 	 * possible.  If the signal would be out of range for S10, return
253 	 * an error to the caller.
254 	 */
255 	sig -= NATIVE_SIGRTMIN;
256 
257 	if (sig > (S10_SIGRTMAX - S10_SIGRTMIN))
258 		return (-1);
259 
260 	return (S10_SIGRTMIN + sig);
261 }
262 
263 /*
264  * Convert a native sigset_t to its S10 version.
265  */
266 int
267 nativesigset_to_s10(const sigset_t *native_set, sigset_t *s10_set)
268 {
269 	int sig;
270 	int s10sig;
271 	sigset_t srcset, newset;
272 
273 	if (brand_uucopy(native_set, &srcset, sizeof (sigset_t)) != 0)
274 		return (EFAULT);
275 
276 	(void) sigemptyset(&newset);
277 
278 	/*
279 	 * Shortcut: we know the first 32 signals are the same in both
280 	 * s10 and native Solaris.  Just assign the first word.
281 	 */
282 	newset.__sigbits[0] = srcset.__sigbits[0];
283 
284 	/*
285 	 * Copy the remainder of the initial set of common signals.
286 	 */
287 	for (sig = 33; sig <= SIGJVM2; sig++)
288 		if (SIGISMEMBER(&srcset, sig))
289 			SIGADDSET(&newset, sig);
290 
291 	/* convert any RT signals to their S10 values */
292 	for (sig = NATIVE_SIGRTMIN; sig <= NATIVE_SIGRTMAX; sig++) {
293 		if (SIGISMEMBER(&srcset, sig) &&
294 		    (s10sig = nativesig_to_s10(sig)) > 0)
295 			SIGADDSET(&newset, s10sig);
296 	}
297 
298 	if (brand_uucopy(&newset, s10_set, sizeof (sigset_t)) != 0)
299 		return (EFAULT);
300 
301 	return (0);
302 }
303 
304 /*
305  * This is our interposed signal handler.
306  * Fix up the arguments received from the kernel and jump
307  * to the s10 signal handler, normally libc's sigacthandler().
308  */
309 static void
310 s10_sigacthandler(int sig, siginfo_t *sip, void *uvp)
311 {
312 	int s10_sig;
313 	ucontext_t *ucp;
314 
315 	s10_sig = nativesig_to_s10(sig);
316 	if (s10_sig <= 0)	/* can't happen? */
317 		brand_abort(sig, "Received an impossible signal");
318 	if (sip != NULL) {
319 		/*
320 		 * All we really have to do is map the signal number,
321 		 * which changes only for the realtime signals,
322 		 * so all the rest of the siginfo structure is the
323 		 * same between s10 and native.
324 		 */
325 		if (sip->si_signo != sig)	/* can't happen? */
326 			brand_abort(sig, "Received an impossible siginfo");
327 		sip->si_signo = s10_sig;
328 	}
329 	if ((ucp = uvp) != NULL &&
330 	    (ucp->uc_flags & UC_SIGMASK))
331 		(void) nativesigset_to_s10(&ucp->uc_sigmask, &ucp->uc_sigmask);
332 
333 	s10_handlers[s10_sig - 1](s10_sig, sip, uvp);
334 }
335 
336 /*
337  * Interposition upon SYS_lwp_sigmask
338  */
339 int
340 s10_lwp_sigmask(sysret_t *rval, int how, uint_t bits0, uint_t bits1)
341 {
342 	sigset_t s10_blockset;
343 	sigset_t native_blockset;
344 	int err;
345 
346 	s10_blockset.__sigbits[0] = bits0;
347 	s10_blockset.__sigbits[1] = bits1;
348 	s10_blockset.__sigbits[2] = 0;
349 	s10_blockset.__sigbits[3] = 0;
350 
351 	(void) s10sigset_to_native(&s10_blockset, &native_blockset);
352 
353 	err = __systemcall(rval, SYS_lwp_sigmask + 1024,
354 	    how,
355 	    native_blockset.__sigbits[0],
356 	    native_blockset.__sigbits[1],
357 	    native_blockset.__sigbits[2],
358 	    native_blockset.__sigbits[3]);
359 
360 	if (err != 0)
361 		return (err);
362 
363 	native_blockset.__sigbits[0] = (int)rval->sys_rval1;
364 	native_blockset.__sigbits[1] = (int)rval->sys_rval2;
365 	native_blockset.__sigbits[2] = 0;
366 	native_blockset.__sigbits[3] = 0;
367 
368 	(void) nativesigset_to_s10(&native_blockset, &s10_blockset);
369 
370 	rval->sys_rval1 = s10_blockset.__sigbits[0];
371 	rval->sys_rval2 = s10_blockset.__sigbits[1];
372 
373 	return (0);
374 }
375 
376 /*
377  * Interposition upon SYS_sigprocmask
378  */
379 int
380 s10_sigprocmask(sysret_t *rval, int how, const sigset_t *set, sigset_t *oset)
381 {
382 	sigset_t sigset_set, sigset_oset;
383 	sigset_t *set_ptr, *oset_ptr;
384 	int err;
385 
386 	oset_ptr = (oset == NULL) ? NULL : &sigset_oset;
387 	set_ptr = (set == NULL) ? NULL : &sigset_set;
388 
389 	if (set_ptr != NULL &&
390 	    (err = s10sigset_to_native(set, set_ptr)) != 0)
391 		return (err);
392 
393 	if ((err = __systemcall(rval, SYS_sigprocmask + 1024,
394 	    how, set_ptr, oset_ptr)) != 0)
395 		return (err);
396 
397 	if (oset_ptr != NULL &&
398 	    (err = nativesigset_to_s10(oset_ptr, oset)) != 0)
399 		return (err);
400 
401 	return (0);
402 }
403 
404 /*
405  * Interposition upon SYS_sigsuspend
406  */
407 int
408 s10_sigsuspend(sysret_t *rval, const sigset_t *set)
409 {
410 	sigset_t sigset_set;
411 	int err;
412 
413 	if ((err = s10sigset_to_native(set, &sigset_set)) != 0) {
414 		(void) B_TRUSS_POINT_1(rval, SYS_sigsuspend, err, set);
415 		return (err);
416 	}
417 
418 	return (__systemcall(rval, SYS_sigsuspend + 1024, &sigset_set));
419 }
420 
421 /*
422  * Interposition upon SYS_sigaction
423  *
424  * There is a fair amount of complexity here due to the need to interpose
425  * on any registered user signal handler.
426  *
427  * The idea is that if a user signal handler is installed, we must install
428  * our own signal handler between the system and the signal handler being
429  * registered.  If the signal handler to be registered is SIG_DFL or SIG_IGN,
430  * we should remove our interpositioned handler as it's no longer needed.
431  *
432  * The way we do this is we set the signal handler to call s10_sigacthandler(),
433  * and then store the address of the passed signal handler in a global
434  * per-process array, s10_handlers[].
435  *
436  * We rely on the fact that the s10 libc blocks all signals during
437  * its call to the sigaction() system call to guarantee atomicity.
438  */
439 int
440 s10_sigaction(sysret_t *rval,
441     int sig, const struct sigaction *act, struct sigaction *oact)
442 {
443 	struct sigaction sigact, osigact;
444 	struct sigaction *sigactp, *osigactp;
445 	int err, nativesig;
446 	void (*handler)();
447 
448 	if ((nativesig = s10sig_to_native(sig)) < 0) {
449 		(void) B_TRUSS_POINT_3(rval, SYS_sigaction, EINVAL,
450 		    sig, act, oact);
451 		return (EINVAL);
452 	}
453 
454 	if (act == NULL) {
455 		sigactp = NULL;
456 	} else {
457 		sigactp = &sigact;
458 
459 		if (brand_uucopy(act, sigactp, sizeof (struct sigaction)) != 0)
460 			return (EFAULT);
461 
462 		if ((err = s10sigset_to_native(&sigactp->sa_mask,
463 		    &sigactp->sa_mask)) != 0) {
464 			(void) B_TRUSS_POINT_3(rval, SYS_sigaction, err,
465 			    sig, act, oact);
466 			return (err);
467 		}
468 	}
469 
470 	osigactp = ((oact == NULL) ? NULL : &osigact);
471 
472 	if (sigactp != NULL) {
473 		handler = sigactp->sa_handler;
474 		if (handler != SIG_DFL && handler != SIG_IGN)
475 			sigactp->sa_handler = s10_sigacthandler;
476 	}
477 
478 	if ((err = __systemcall(rval, SYS_sigaction + 1024,
479 	    nativesig, sigactp, osigactp)) != 0)
480 		return (err);
481 
482 	/*
483 	 * Translate the old signal mask if we are supposed to return the old
484 	 * struct sigaction.
485 	 *
486 	 * Note that we may have set the signal handler, but may return EFAULT
487 	 * here if the oact parameter is bad.
488 	 *
489 	 * That's OK, because the direct system call acts the same way.
490 	 */
491 	if (osigactp != NULL) {
492 		err = nativesigset_to_s10(&osigactp->sa_mask,
493 		    &osigactp->sa_mask);
494 
495 		if (osigactp->sa_handler == s10_sigacthandler)
496 			osigactp->sa_handler = s10_handlers[sig - 1];
497 
498 		if (err == 0 && brand_uucopy(osigactp, oact,
499 		    sizeof (struct sigaction)) != 0)
500 			err = EFAULT;
501 	}
502 
503 	/*
504 	 * Do not store SIG_DFL or SIG_IGN into the array of remembered
505 	 * signal handlers.  Only store bona-fide function addresses.
506 	 * This is to avoid a race condition in which some thread
507 	 * sets the signal handler to SIG_DFL or SIG_IGN while some
508 	 * other thread is fielding the signal but has not yet reached
509 	 * s10_sigacthandler().  s10_sigacthandler() will unconditionally
510 	 * call the remembered signal handler and it it calls SIG_DFL or
511 	 * SIG_IGN, the process will incur a SIGSEGV or SIGBUS signal.
512 	 * This also allows a vfork() child to set signal handlers
513 	 * to SIG_DFL or SIG_IGN without corrupting the parent's
514 	 * address space.
515 	 */
516 	if (sigactp != NULL &&
517 	    handler != SIG_DFL && handler != SIG_IGN)
518 		s10_handlers[sig - 1] = handler;
519 
520 	return (err);
521 }
522 
523 /*
524  * Interposition upon SYS_sigpending
525  */
526 int
527 s10_sigpending(sysret_t *rval, int flag, sigset_t *set)
528 {
529 	sigset_t sigset_set;
530 	int err;
531 
532 	if ((err = __systemcall(rval, SYS_sigpending + 1024,
533 	    flag, &sigset_set)) != 0)
534 		return (err);
535 
536 	if ((err = nativesigset_to_s10(&sigset_set, set)) != 0)
537 		return (err);
538 
539 	return (0);
540 }
541 
542 /*
543  * Interposition upon SYS_sigsendsys
544  */
545 int
546 s10_sigsendsys(sysret_t *rval, procset_t *psp, int sig)
547 {
548 	int nativesig;
549 
550 	if ((nativesig = s10sig_to_native(sig)) < 0) {
551 		(void) B_TRUSS_POINT_2(rval, SYS_sigsendsys, EINVAL,
552 		    psp, sig);
553 		return (EINVAL);
554 	}
555 
556 	return (__systemcall(rval, SYS_sigsendsys + 1024, psp, nativesig));
557 }
558 
559 /*
560  * Convert the siginfo_t code and status fields to an old style
561  * wait status for s10_wait(), below.
562  */
563 static int
564 wstat(int code, int status)
565 {
566 	int stat = (status & 0377);
567 
568 	switch (code) {
569 	case CLD_EXITED:
570 		stat <<= 8;
571 		break;
572 	case CLD_DUMPED:
573 		stat |= WCOREFLG;
574 		break;
575 	case CLD_KILLED:
576 		break;
577 	case CLD_TRAPPED:
578 	case CLD_STOPPED:
579 		stat <<= 8;
580 		stat |= WSTOPFLG;
581 		break;
582 	case CLD_CONTINUED:
583 		stat = WCONTFLG;
584 		break;
585 	}
586 	return (stat);
587 }
588 
589 /*
590  * Interposition upon SYS_wait
591  */
592 int
593 s10_wait(sysret_t *rval)
594 {
595 	int err;
596 	siginfo_t info;
597 
598 	err = s10_waitid(rval, P_ALL, 0, &info, WEXITED | WTRAPPED);
599 	if (err != 0)
600 		return (err);
601 
602 	rval->sys_rval1 = info.si_pid;
603 	rval->sys_rval2 = wstat(info.si_code, info.si_status);
604 
605 	return (0);
606 }
607 
608 /*
609  * Interposition upon SYS_waitid
610  */
611 int
612 s10_waitid(sysret_t *rval,
613     idtype_t idtype, id_t id, siginfo_t *infop, int options)
614 {
615 	int err, sig;
616 
617 	err = __systemcall(rval, SYS_waitid + 1024, idtype, id, infop, options);
618 	if (err != 0)
619 		return (err);
620 
621 	/*
622 	 * If the process being waited for terminated or stopped due to a
623 	 * signal, translate the signal number from its native value to its
624 	 * S10 equivalent.
625 	 *
626 	 * If we can't legally translate the signal number, just sort of punt
627 	 * and leave it untranslated.
628 	 *
629 	 * We shouldn't return EINVAL as the syscall didn't technically fail.
630 	 */
631 	if (infop->si_signo == SIGCLD && infop->si_code != CLD_EXITED &&
632 	    (sig = nativesig_to_s10(infop->si_status)) > 0)
633 		infop->si_status = sig;
634 
635 	return (0);
636 }
637 
638 /*
639  * Interposition upon SYS_sigtimedwait
640  */
641 int
642 s10_sigtimedwait(sysret_t *rval,
643     const sigset_t *set, siginfo_t *info, const timespec_t *timeout)
644 {
645 	sigset_t sigset_set;
646 	int err, sig;
647 
648 	if ((err = s10sigset_to_native(set, &sigset_set)) != 0) {
649 		(void) B_TRUSS_POINT_3(rval, SYS_sigtimedwait, err,
650 		    set, info, timeout);
651 		return (err);
652 	}
653 
654 	if ((err = __systemcall(rval, SYS_sigtimedwait + 1024,
655 	    &sigset_set, info, timeout)) != 0)
656 		return (err);
657 
658 	if (info != NULL) {
659 		/*
660 		 * If we can't legally translate the signal number in the
661 		 * siginfo_t, just sort of punt and leave it untranslated.
662 		 *
663 		 * We shouldn't return EINVAL as the syscall didn't technically
664 		 * fail.
665 		 */
666 		if ((sig = nativesig_to_s10(info->si_signo)) > 0)
667 			info->si_signo = sig;
668 	}
669 
670 	/*
671 	 * If we can't legally translate the signal number returned by the
672 	 * sigtimedwait syscall, just sort of punt and leave it untranslated.
673 	 *
674 	 * We shouldn't return EINVAL as the syscall didn't technically
675 	 * fail.
676 	 */
677 	if ((sig = nativesig_to_s10((int)rval->sys_rval1)) > 0)
678 		rval->sys_rval1 = sig;
679 
680 	return (0);
681 }
682 
683 /*
684  * Interposition upon SYS_sigqueue
685  */
686 int
687 s10_sigqueue(sysret_t *rval, pid_t pid, int signo, void *value, int si_code)
688 {
689 	int nativesig;
690 
691 	if ((nativesig = s10sig_to_native(signo)) < 0) {
692 		(void) B_TRUSS_POINT_4(rval, SYS_sigqueue, EINVAL,
693 		    pid, signo, value, si_code);
694 		return (EINVAL);
695 	}
696 
697 	if (pid == 1)
698 		pid = zone_init_pid;
699 
700 	/*
701 	 * The native version of this syscall takes an extra argument.
702 	 * The new last arg "block" flag should be zero.  The block flag
703 	 * is used by the Opensolaris AIO implementation, which is now
704 	 * part of libc.
705 	 */
706 	return (__systemcall(rval, SYS_sigqueue + 1024,
707 	    pid, nativesig, value, si_code, 0));
708 }
709 
710 /*
711  * Interposition upon SYS_signotify
712  */
713 int
714 s10_signotify(sysret_t *rval,
715     int cmd, siginfo_t *siginfo, signotify_id_t *sn_id)
716 {
717 	siginfo_t *infop, info;
718 
719 	infop = siginfo;
720 
721 	/* only check for a valid siginfo pointer in the case of SN_PROC */
722 	if (cmd == SN_PROC) {
723 		int nativesig;
724 
725 		if (brand_uucopy(infop, &info, sizeof (siginfo_t)) != 0)
726 			return (EFAULT);
727 
728 		if ((nativesig = s10sig_to_native(info.si_signo)) < 0) {
729 			(void) B_TRUSS_POINT_3(rval, SYS_signotify, EINVAL,
730 			    cmd, siginfo, sn_id);
731 			return (EINVAL);
732 		}
733 
734 		info.si_signo = nativesig;
735 		infop = &info;
736 	}
737 
738 	return (__systemcall(rval, SYS_signotify + 1024, cmd, infop, sn_id));
739 }
740 
741 /*
742  * Interposition upon SYS_kill
743  */
744 int
745 s10_kill(sysret_t *rval, pid_t pid, int sig)
746 {
747 	int nativesig;
748 
749 	if ((nativesig = s10sig_to_native(sig)) < 0) {
750 		(void) B_TRUSS_POINT_2(rval, SYS_kill, EINVAL, pid, sig);
751 		return (EINVAL);
752 	}
753 
754 	if (pid == 1)
755 		pid = zone_init_pid;
756 
757 	return (__systemcall(rval, SYS_kill + 1024, pid, nativesig));
758 }
759 
760 /*
761  * Interposition upon SYS_lwp_create
762  *
763  * See also the s10_lwp_create_correct_fs() function in s10_brand.c
764  * for the special case of creating an lwp in a 64-bit x86 process.
765  */
766 int
767 s10_lwp_create(sysret_t *rval, ucontext_t *ucp, int flags, id_t *new_lwp)
768 {
769 	ucontext_t s10_uc;
770 
771 	if (brand_uucopy(ucp, &s10_uc, sizeof (ucontext_t)) != 0)
772 		return (EFAULT);
773 
774 	if (s10_uc.uc_flags & UC_SIGMASK)
775 		(void) s10sigset_to_native(&s10_uc.uc_sigmask,
776 		    &s10_uc.uc_sigmask);
777 
778 	return (__systemcall(rval, SYS_lwp_create + 1024,
779 	    &s10_uc, flags, new_lwp));
780 }
781 
782 /*
783  * Interposition upon SYS_lwp_kill
784  */
785 int
786 s10_lwp_kill(sysret_t *rval, id_t lwpid, int sig)
787 {
788 	int nativesig;
789 
790 	if ((nativesig = s10sig_to_native(sig)) < 0) {
791 		(void) B_TRUSS_POINT_2(rval, SYS_lwp_kill, EINVAL,
792 		    lwpid, sig);
793 		return (EINVAL);
794 	}
795 
796 	return (__systemcall(rval, SYS_lwp_kill + 1024, lwpid, nativesig));
797 }
798