Print this page
OS-4470 lxbrand unblocking signals in new threads must be atomic


 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         }