Print this page
OS-3561 lxbrand emulation library should execute on alternate stack
OS-3558 lxbrand add support for full in-kernel syscall handling
OS-3545 lx_syscall_regs should not walk stack
OS-3868 many LTP testcases now hang
OS-3901 lxbrand lx_recvmsg fails to translate control messages when 64-bit
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Bryan Cantrill <bryan@joyent.com>

@@ -18,10 +18,13 @@
  *
  * CDDL HEADER END
  */
 
 /*
+ * Copyright 2015 Joyent, Inc.
+ */
+/*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 /*      Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */

@@ -85,10 +88,12 @@
 #include <sys/promif.h>
 #include <sys/systeminfo.h>
 #include <sys/kdi.h>
 #include <sys/contract_impl.h>
 #include <sys/x86_archext.h>
+#include <sys/brand.h>
+#include <sys/sdt.h>
 
 /*
  * Construct the execution environment for the user's signal
  * handler and arrange for control to be given to it on return
  * to userland.  The library code now calls setcontext() to

@@ -184,11 +189,22 @@
          * context.  on_fault will catch any faults.
          */
         newstack = sigismember(&PTOU(curproc)->u_sigonstack, sig) &&
             !(lwp->lwp_sigaltstack.ss_flags & (SS_ONSTACK|SS_DISABLE));
 
-        if (newstack) {
+        /*
+         * If this is a branded process, the brand may provide an alternate
+         * stack pointer for signal delivery:
+         */
+        if (PROC_IS_BRANDED(p) && BROP(p)->b_sendsig_stack != NULL) {
+                /*
+                 * Use the stack pointer value provided by the brand,
+                 * accounting for the 128-byte reserved region.
+                 */
+                newstack = 0;
+                fp = BROP(p)->b_sendsig_stack(sig) - STACK_RESERVE;
+        } else if (newstack) {
                 fp = (caddr_t)(SA((uintptr_t)lwp->lwp_sigaltstack.ss_sp) +
                     SA(lwp->lwp_sigaltstack.ss_size) - STACK_ALIGN);
         } else {
                 /*
                  * Drop below the 128-byte reserved region of the stack frame

@@ -294,10 +310,12 @@
                 goto badstack;
         copyout_noerr(tuc, uc, sizeof (*tuc));
         kmem_free(tuc, sizeof (*tuc));
         tuc = NULL;
 
+        DTRACE_PROBE3(oldcontext__set, klwp_t *, lwp,
+            uintptr_t, lwp->lwp_oldcontext, uintptr_t, (uintptr_t)uc);
         lwp->lwp_oldcontext = (uintptr_t)uc;
 
         if (newstack) {
                 lwp->lwp_sigaltstack.ss_flags |= SS_ONSTACK;
                 if (lwp->lwp_ustack)

@@ -343,10 +361,18 @@
                 rp->r_cs = UCS_SEL;
                 rp->r_ss = UDS_SEL;
         }
 
         /*
+         * Allow the brand to perform additional book-keeping once the signal
+         * handling frame has been fully assembled:
+         */
+        if (PROC_IS_BRANDED(p) && BROP(p)->b_sendsig != NULL) {
+                BROP(p)->b_sendsig(sig);
+        }
+
+        /*
          * Don't set lwp_eosys here.  sendsig() is called via psig() after
          * lwp_eosys is handled, so setting it here would affect the next
          * system call.
          */
         return (1);

@@ -418,11 +444,21 @@
          * context.  on_fault will catch any faults.
          */
         newstack = sigismember(&PTOU(curproc)->u_sigonstack, sig) &&
             !(lwp->lwp_sigaltstack.ss_flags & (SS_ONSTACK|SS_DISABLE));
 
-        if (newstack) {
+        /*
+         * If this is a branded process, the brand may provide an alternate
+         * stack pointer for signal delivery:
+         */
+        if (PROC_IS_BRANDED(p) && BROP(p)->b_sendsig_stack != NULL) {
+                /*
+                 * Use the stack pointer value provided by the brand:
+                 */
+                newstack = 0;
+                fp = BROP(p)->b_sendsig_stack(sig);
+        } else if (newstack) {
                 fp = (caddr_t)(SA32((uintptr_t)lwp->lwp_sigaltstack.ss_sp) +
                     SA32(lwp->lwp_sigaltstack.ss_size) - STACK_ALIGN32);
         } else if ((rp->r_ss & 0xffff) != UDS_SEL) {
                 user_desc_t *ldt;
                 /*

@@ -433,12 +469,13 @@
                 if ((ldt = p->p_ldt) != NULL)
                         fp = (caddr_t)rp->r_sp +
                             USEGD_GETBASE(&ldt[SELTOIDX(rp->r_ss)]);
                 else
                         fp = (caddr_t)rp->r_sp;
-        } else
+        } else {
                 fp = (caddr_t)rp->r_sp;
+        }
 
         /*
          * Force proper stack pointer alignment, even in the face of a
          * misaligned stack pointer from user-level before the signal.
          * Don't use the SA32() macro because that rounds up, not down.

@@ -515,10 +552,12 @@
                 goto badstack;
         copyout_noerr(tuc, uc, sizeof (*tuc));
         kmem_free(tuc, sizeof (*tuc));
         tuc = NULL;
 
+        DTRACE_PROBE3(oldcontext__set, klwp_t *, lwp,
+            uintptr_t, lwp->lwp_oldcontext, uintptr_t, (uintptr_t)uc);
         lwp->lwp_oldcontext = (uintptr_t)uc;
 
         if (newstack) {
                 lwp->lwp_sigaltstack.ss_flags |= SS_ONSTACK;
                 if (lwp->lwp_ustack) {

@@ -564,10 +603,18 @@
                 rp->r_cs = U32CS_SEL;
                 rp->r_ss = UDS_SEL;
         }
 
         /*
+         * Allow the brand to perform additional book-keeping once the signal
+         * handling frame has been fully assembled:
+         */
+        if (PROC_IS_BRANDED(p) && BROP(p)->b_sendsig != NULL) {
+                BROP(p)->b_sendsig(sig);
+        }
+
+        /*
          * Don't set lwp_eosys here.  sendsig() is called via psig() after
          * lwp_eosys is handled, so setting it here would affect the next
          * system call.
          */
         return (1);

@@ -641,11 +688,21 @@
          * context. on_fault will catch any faults.
          */
         newstack = sigismember(&PTOU(curproc)->u_sigonstack, sig) &&
             !(lwp->lwp_sigaltstack.ss_flags & (SS_ONSTACK|SS_DISABLE));
 
-        if (newstack) {
+        /*
+         * If this is a branded process, the brand may provide an alternate
+         * stack pointer for signal delivery:
+         */
+        if (PROC_IS_BRANDED(p) && BROP(p)->b_sendsig_stack != NULL) {
+                /*
+                 * Use the stack pointer value provided by the brand:
+                 */
+                newstack = 0;
+                fp = BROP(p)->b_sendsig_stack(sig);
+        } else if (newstack) {
                 fp = (caddr_t)(SA((uintptr_t)lwp->lwp_sigaltstack.ss_sp) +
                     SA(lwp->lwp_sigaltstack.ss_size) - STACK_ALIGN);
         } else if ((rp->r_ss & 0xffff) != UDS_SEL) {
                 user_desc_t *ldt;
                 /*

@@ -656,12 +713,13 @@
                 if ((ldt = p->p_ldt) != NULL)
                         fp = (caddr_t)rp->r_sp +
                             USEGD_GETBASE(&ldt[SELTOIDX(rp->r_ss)]);
                 else
                         fp = (caddr_t)rp->r_sp;
-        } else
+        } else {
                 fp = (caddr_t)rp->r_sp;
+        }
 
         /*
          * Force proper stack pointer alignment, even in the face of a
          * misaligned stack pointer from user-level before the signal.
          * Don't use the SA() macro because that rounds up, not down.

@@ -735,10 +793,12 @@
         savecontext(tuc, &lwp->lwp_sigoldmask);
         copyout_noerr(tuc, uc, sizeof (*tuc));
         kmem_free(tuc, sizeof (*tuc));
         tuc = NULL;
 
+        DTRACE_PROBE3(oldcontext__set, klwp_t *, lwp,
+            uintptr_t, lwp->lwp_oldcontext, uintptr_t, (uintptr_t)uc);
         lwp->lwp_oldcontext = (uintptr_t)uc;
 
         if (newstack) {
                 lwp->lwp_sigaltstack.ss_flags |= SS_ONSTACK;
                 if (lwp->lwp_ustack)

@@ -771,10 +831,18 @@
             (rp->r_ss & 0xffff) != UDS_SEL) {
                 rp->r_cs = UCS_SEL;
                 rp->r_ss = UDS_SEL;
         }
 
+        /*
+         * Allow the brand to perform additional book-keeping once the signal
+         * handling frame has been fully assembled:
+         */
+        if (PROC_IS_BRANDED(p) && BROP(p)->b_sendsig != NULL) {
+                BROP(p)->b_sendsig(sig);
+        }
+
         /*
          * Don't set lwp_eosys here.  sendsig() is called via psig() after
          * lwp_eosys is handled, so setting it here would affect the next
          * system call.
          */