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) 1984, 1986, 1987, 1988, 1989 AT&T */

@@ -44,10 +47,11 @@
 #include <sys/errno.h>
 #include <sys/archsystm.h>
 #include <sys/schedctl.h>
 #include <sys/debug.h>
 #include <sys/sysmacros.h>
+#include <sys/sdt.h>
 
 /*
  * Save user context.
  */
 void

@@ -123,11 +127,27 @@
         if (lwp->lwp_pcb.pcb_fpu.fpu_flags & FPU_EN)
                 getfpregs(lwp, &ucp->uc_mcontext.fpregs);
         else
                 ucp->uc_flags &= ~UC_FPU;
 
+        if (mask != NULL) {
+                /*
+                 * Save signal mask.
+                 */
         sigktou(mask, &ucp->uc_sigmask);
+        } else {
+                ucp->uc_flags &= ~UC_SIGMASK;
+                bzero(&ucp->uc_sigmask, sizeof (ucp->uc_sigmask));
+        }
+
+        if (PROC_IS_BRANDED(p) && BROP(p)->b_savecontext != NULL) {
+                /*
+                 * Allow the brand the chance to modify the context we
+                 * saved:
+                 */
+                BROP(p)->b_savecontext(ucp);
+        }
 }
 
 /*
  * Restore user context.
  */

@@ -134,11 +154,23 @@
 void
 restorecontext(ucontext_t *ucp)
 {
         kthread_t *t = curthread;
         klwp_t *lwp = ttolwp(t);
+        proc_t *p = lwptoproc(lwp);
 
+        if (PROC_IS_BRANDED(p) && BROP(p)->b_restorecontext != NULL) {
+                /*
+                 * Allow the brand the chance to modify the context before
+                 * we restore it:
+                 */
+                BROP(p)->b_restorecontext(ucp);
+        }
+
+        DTRACE_PROBE3(oldcontext__set, klwp_t *, lwp,
+            uintptr_t, lwp->lwp_oldcontext,
+            uintptr_t, (uintptr_t)ucp->uc_link);
         lwp->lwp_oldcontext = (uintptr_t)ucp->uc_link;
 
         if (ucp->uc_flags & UC_STACK) {
                 if (ucp->uc_stack.ss_flags == SS_ONSTACK)
                         lwp->lwp_sigaltstack = ucp->uc_stack;

@@ -182,10 +214,11 @@
 {
         ucontext_t uc;
         ucontext_t *ucp;
         klwp_t *lwp = ttolwp(curthread);
         stack_t dummy_stk;
+        proc_t *p = lwptoproc(lwp);
 
         /*
          * In future releases, when the ucontext structure grows,
          * getcontext should be modified to only return the fields
          * specified in the uc_flags.  That way, the structure can grow

@@ -226,10 +259,19 @@
                     copyin(&ucp->uc_mcontext.fpregs, &uc.uc_mcontext.fpregs,
                     sizeof (uc.uc_mcontext.fpregs))) {
                         return (set_errno(EFAULT));
                 }
 
+                /*
+                 * If this is a branded process, copy in the brand-private
+                 * data:
+                 */
+                if (PROC_IS_BRANDED(p) && copyin(&ucp->uc_brand_data,
+                    &uc.uc_brand_data, sizeof (uc.uc_brand_data)) != 0) {
+                        return (set_errno(EFAULT));
+                }
+
                 restorecontext(&uc);
 
                 if ((uc.uc_flags & UC_STACK) && (lwp->lwp_ustack != 0))
                         (void) copyout(&uc.uc_stack, (stack_t *)lwp->lwp_ustack,
                             sizeof (uc.uc_stack));

@@ -309,11 +351,27 @@
         if (lwp->lwp_pcb.pcb_fpu.fpu_flags & FPU_EN)
                 getfpregs32(lwp, &ucp->uc_mcontext.fpregs);
         else
                 ucp->uc_flags &= ~UC_FPU;
 
+        if (mask != NULL) {
+                /*
+                 * Save signal mask.
+                 */
         sigktou(mask, &ucp->uc_sigmask);
+        } else {
+                ucp->uc_flags &= ~UC_SIGMASK;
+                bzero(&ucp->uc_sigmask, sizeof (ucp->uc_sigmask));
+        }
+
+        if (PROC_IS_BRANDED(p) && BROP(p)->b_savecontext32 != NULL) {
+                /*
+                 * Allow the brand the chance to modify the context we
+                 * saved:
+                 */
+                BROP(p)->b_savecontext32(ucp);
+        }
 }
 
 int
 getsetcontext32(int flag, void *arg)
 {

@@ -321,10 +379,11 @@
         ucontext_t ucnat;
         ucontext32_t *ucp;
         klwp_t *lwp = ttolwp(curthread);
         caddr32_t ustack32;
         stack32_t dummy_stk32;
+        proc_t *p = lwptoproc(lwp);
 
         switch (flag) {
         default:
                 return (set_errno(EINVAL));
 

@@ -351,10 +410,19 @@
                 if ((uc.uc_flags & UC_FPU) &&
                     copyin(&ucp->uc_mcontext.fpregs, &uc.uc_mcontext.fpregs,
                     sizeof (uc.uc_mcontext.fpregs))) {
                         return (set_errno(EFAULT));
                 }
+
+                /*
+                 * If this is a branded process, copy in the brand-private
+                 * data:
+                 */
+                if (PROC_IS_BRANDED(p) && copyin(&ucp->uc_brand_data,
+                    &uc.uc_brand_data, sizeof (uc.uc_brand_data)) != 0) {
+                        return (set_errno(EFAULT));
+                }
 
                 ucontext_32ton(&uc, &ucnat);
                 restorecontext(&ucnat);
 
                 if ((uc.uc_flags & UC_STACK) && (lwp->lwp_ustack != 0))