523
524 /*
525 * setcontext() has code that forcibly restores the curthread
526 * pointer in a context passed to the setcontext(2) syscall.
527 *
528 * Certain processes may need to disable this feature, so these routines
529 * provide the mechanism to do so.
530 *
531 * (As an example, branded 32-bit x86 processes may use %gs for their own
532 * purposes, so they need to be able to specify a %gs value to be restored
533 * on return from a signal handler via the passed ucontext_t.)
534 */
535 static int setcontext_enforcement = 1;
536
537 void
538 set_setcontext_enforcement(int on)
539 {
540 setcontext_enforcement = on;
541 }
542
543 #pragma weak _setcontext = setcontext
544 int
545 setcontext(const ucontext_t *ucp)
546 {
547 ulwp_t *self = curthread;
548 uberdata_t *udp = self->ul_uberdata;
549 int ret;
550 ucontext_t uc;
551
552 /*
553 * Returning from the main context (uc_link == NULL) causes
554 * the thread to exit. See setcontext(2) and makecontext(3C).
555 */
556 if (ucp == NULL)
557 thr_exit(NULL);
558 (void) memcpy(&uc, ucp, sizeof (uc));
559
560 /*
561 * Restore previous signal mask and context link.
562 */
563 if (uc.uc_flags & UC_SIGMASK) {
564 block_all_signals(self);
565 delete_reserved_signals(&uc.uc_sigmask);
566 self->ul_sigmask = uc.uc_sigmask;
567 if (self->ul_cursig) {
568 /*
569 * We have a deferred signal present.
570 * The signal mask will be set when the
571 * signal is taken in take_deferred_signal().
572 */
573 ASSERT(self->ul_critical + self->ul_sigdefer != 0);
574 uc.uc_flags &= ~UC_SIGMASK;
575 }
576 }
577 self->ul_siglink = uc.uc_link;
578
579 /*
580 * We don't know where this context structure has been.
581 * Preserve the curthread pointer, at least.
582 *
583 * Allow this feature to be disabled if a particular process
584 * requests it.
585 */
586 if (setcontext_enforcement) {
587 #if defined(__sparc)
588 uc.uc_mcontext.gregs[REG_G7] = (greg_t)self;
589 #elif defined(__amd64)
590 uc.uc_mcontext.gregs[REG_FS] = (greg_t)0; /* null for fsbase */
591 #elif defined(__i386)
592 uc.uc_mcontext.gregs[GS] = (greg_t)LWPGS_SEL;
593 #else
594 #error "none of __sparc, __amd64, __i386 defined"
595 #endif
596 }
|
523
524 /*
525 * setcontext() has code that forcibly restores the curthread
526 * pointer in a context passed to the setcontext(2) syscall.
527 *
528 * Certain processes may need to disable this feature, so these routines
529 * provide the mechanism to do so.
530 *
531 * (As an example, branded 32-bit x86 processes may use %gs for their own
532 * purposes, so they need to be able to specify a %gs value to be restored
533 * on return from a signal handler via the passed ucontext_t.)
534 */
535 static int setcontext_enforcement = 1;
536
537 void
538 set_setcontext_enforcement(int on)
539 {
540 setcontext_enforcement = on;
541 }
542
543 /*
544 * The LX brand emulation library implements an operation that is analogous to
545 * setcontext(), but takes a different path in to the kernel. So that it can
546 * correctly restore a signal mask, we expose just the signal mask handling
547 * part of the regular setcontext() routine as a private interface.
548 */
549 void
550 setcontext_sigmask(ucontext_t *ucp)
551 {
552 ulwp_t *self = curthread;
553
554 if (ucp->uc_flags & UC_SIGMASK) {
555 block_all_signals(self);
556 delete_reserved_signals(&ucp->uc_sigmask);
557 self->ul_sigmask = ucp->uc_sigmask;
558 if (self->ul_cursig) {
559 /*
560 * We have a deferred signal present.
561 * The signal mask will be set when the
562 * signal is taken in take_deferred_signal().
563 */
564 ASSERT(self->ul_critical + self->ul_sigdefer != 0);
565 ucp->uc_flags &= ~UC_SIGMASK;
566 }
567 }
568 }
569
570 #pragma weak _setcontext = setcontext
571 int
572 setcontext(const ucontext_t *ucp)
573 {
574 ulwp_t *self = curthread;
575 uberdata_t *udp = self->ul_uberdata;
576 int ret;
577 ucontext_t uc;
578
579 /*
580 * Returning from the main context (uc_link == NULL) causes
581 * the thread to exit. See setcontext(2) and makecontext(3C).
582 */
583 if (ucp == NULL)
584 thr_exit(NULL);
585 (void) memcpy(&uc, ucp, sizeof (uc));
586
587 /*
588 * Restore previous signal mask and context link.
589 */
590 setcontext_sigmask(&uc);
591 self->ul_siglink = uc.uc_link;
592
593 /*
594 * We don't know where this context structure has been.
595 * Preserve the curthread pointer, at least.
596 *
597 * Allow this feature to be disabled if a particular process
598 * requests it.
599 */
600 if (setcontext_enforcement) {
601 #if defined(__sparc)
602 uc.uc_mcontext.gregs[REG_G7] = (greg_t)self;
603 #elif defined(__amd64)
604 uc.uc_mcontext.gregs[REG_FS] = (greg_t)0; /* null for fsbase */
605 #elif defined(__i386)
606 uc.uc_mcontext.gregs[GS] = (greg_t)LWPGS_SEL;
607 #else
608 #error "none of __sparc, __amd64, __i386 defined"
609 #endif
610 }
|