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


 481         /*
 482          * The AMD64 ABI requires that, on entry to a function, the stack
 483          * pointer must be 8-byte aligned, but _not_ 16-byte aligned.  When
 484          * the frame pointer is pushed, the alignment will then be correct.
 485          */
 486         LX_REG(&lxtsd->lxtsd_exit_context, REG_SP) -= STACK_ENTRY_ALIGN;
 487 #endif
 488 
 489         /*
 490          * Block all signals in the exit context to avoid taking any signals
 491          * (to the degree possible) while exiting.
 492          */
 493         (void) sigfillset(&lxtsd->lxtsd_exit_context.uc_sigmask);
 494 
 495         if ((err = thr_setspecific(lx_tsd_key, lxtsd)) != 0) {
 496                 lx_err_fatal("Unable to initialize thread-specific data: %s",
 497                     strerror(err));
 498         }
 499 }
 500 





















 501 static void
 502 lx_start(uintptr_t sp, uintptr_t entry)
 503 {
 504         ucontext_t jump_uc;
 505 
 506         if (getcontext(&jump_uc) != 0) {
 507                 lx_err_fatal("Unable to getcontext for program start: %s",
 508                     strerror(errno));
 509         }
 510 
 511         /*
 512          * We want to load the general registers from this
 513          * context, and switch to the BRAND stack.
 514          */
 515         jump_uc.uc_flags = UC_CPU;
 516         jump_uc.uc_brand_data[0] = (void *)LX_UC_STACK_BRAND;
 517 
 518         LX_REG(&jump_uc, REG_FP) = NULL;
 519         LX_REG(&jump_uc, REG_SP) = sp;
 520         LX_REG(&jump_uc, REG_PC) = entry;
 521 
 522 #if defined(_LP64)
 523         /*
 524          * The AMD64 ABI states that at process entry, %rdx contains "a
 525          * function pointer that the application should register with
 526          * atexit()".  We make sure to pass NULL explicitly so that
 527          * no function is registered.
 528          */
 529         LX_REG(&jump_uc, REG_RDX) = NULL;
 530 #endif
 531 
 532         lx_debug("starting Linux program sp %p ldentry %p", sp, entry);
 533 
 534         /*
 535          * This system call should not return.
 536          */
 537         if (syscall(SYS_brand, B_JUMP_TO_LINUX, &jump_uc) == -1) {
 538                 lx_err_fatal("B_JUMP_TO_LINUX failed: %s",
 539                     strerror(errno));
 540         }
 541         abort();
 542 }
 543 
 544 /*ARGSUSED*/
 545 int
 546 lx_init(int argc, char *argv[], char *envp[])
 547 {
 548         char            *r;
 549         auxv_t          *ap;
 550         long            *p;
 551         int             err;
 552         lx_elf_data_t   edp;
 553         lx_brand_registration_t reg;
 554         lx_tsd_t        *lxtsd;
 555 #if defined(_LP64)
 556         void            *vdso_hdr;
 557 #endif
 558 
 559         bzero(&reg, sizeof (reg));
 560 
 561         stack_bottom = 2 * sysconf(_SC_PAGESIZE);




 481         /*
 482          * The AMD64 ABI requires that, on entry to a function, the stack
 483          * pointer must be 8-byte aligned, but _not_ 16-byte aligned.  When
 484          * the frame pointer is pushed, the alignment will then be correct.
 485          */
 486         LX_REG(&lxtsd->lxtsd_exit_context, REG_SP) -= STACK_ENTRY_ALIGN;
 487 #endif
 488 
 489         /*
 490          * Block all signals in the exit context to avoid taking any signals
 491          * (to the degree possible) while exiting.
 492          */
 493         (void) sigfillset(&lxtsd->lxtsd_exit_context.uc_sigmask);
 494 
 495         if ((err = thr_setspecific(lx_tsd_key, lxtsd)) != 0) {
 496                 lx_err_fatal("Unable to initialize thread-specific data: %s",
 497                     strerror(err));
 498         }
 499 }
 500 
 501 void
 502 lx_jump_to_linux(ucontext_t *ucp)
 503 {
 504         extern void setcontext_sigmask(ucontext_t *);
 505 
 506         /*
 507          * Call into this private libc interface to allow us to use only the
 508          * signal mask handling part of a regular setcontext() operation.
 509          */
 510         setcontext_sigmask(ucp);
 511 
 512         if (syscall(SYS_brand, B_JUMP_TO_LINUX, ucp) != 0) {
 513                 lx_err_fatal("B_JUMP_TO_LINUX failed: %s", strerror(errno));
 514         }
 515 
 516         /*
 517          * This system call should not return.
 518          */
 519         abort();
 520 }
 521 
 522 static void
 523 lx_start(uintptr_t sp, uintptr_t entry)
 524 {
 525         ucontext_t jump_uc;
 526 
 527         if (getcontext(&jump_uc) != 0) {
 528                 lx_err_fatal("Unable to getcontext for program start: %s",
 529                     strerror(errno));
 530         }
 531 
 532         /*
 533          * We want to load the general registers from this
 534          * context, and switch to the BRAND stack.
 535          */
 536         jump_uc.uc_flags = UC_CPU;
 537         jump_uc.uc_brand_data[0] = (void *)LX_UC_STACK_BRAND;
 538 
 539         LX_REG(&jump_uc, REG_FP) = NULL;
 540         LX_REG(&jump_uc, REG_SP) = sp;
 541         LX_REG(&jump_uc, REG_PC) = entry;
 542 
 543 #if defined(_LP64)
 544         /*
 545          * The AMD64 ABI states that at process entry, %rdx contains "a
 546          * function pointer that the application should register with
 547          * atexit()".  We make sure to pass NULL explicitly so that
 548          * no function is registered.
 549          */
 550         LX_REG(&jump_uc, REG_RDX) = NULL;
 551 #endif
 552 
 553         lx_debug("starting Linux program sp %p ldentry %p", sp, entry);
 554         lx_jump_to_linux(&jump_uc);








 555 }
 556 
 557 /*ARGSUSED*/
 558 int
 559 lx_init(int argc, char *argv[], char *envp[])
 560 {
 561         char            *r;
 562         auxv_t          *ap;
 563         long            *p;
 564         int             err;
 565         lx_elf_data_t   edp;
 566         lx_brand_registration_t reg;
 567         lx_tsd_t        *lxtsd;
 568 #if defined(_LP64)
 569         void            *vdso_hdr;
 570 #endif
 571 
 572         bzero(&reg, sizeof (reg));
 573 
 574         stack_bottom = 2 * sysconf(_SC_PAGESIZE);