Print this page
OS-5354 lx shebang argument handling is incorrect
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
OS-4364 intpexec mishandles process branding
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
OS-4119 lxbrand panic when running native perl inside lx zone
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
        
*** 20,29 ****
--- 20,30 ----
   */
  /*
   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
   * Use is subject to license terms.
   * Copyright 2012 Milan Jurik. All rights reserved.
+  * Copyright 2016, Joyent, Inc.
   */
  
  /*      Copyright (c) 1988 AT&T */
  /*        All Rights Reserved   */
  
*** 45,62 ****
  #include <sys/disp.h>
  #include <sys/exec.h>
  #include <sys/kmem.h>
  #include <sys/note.h>
  #include <sys/sdt.h>
  
  /*
   * This is the loadable module wrapper.
   */
  #include <sys/modctl.h>
  
  extern int intpexec(struct vnode *, struct execa *, struct uarg *,
!     struct intpdata *, int, long *, int, caddr_t, struct cred *, int);
  
  static struct execsw esw = {
          intpmagicstr,
          0,
          2,
--- 46,64 ----
  #include <sys/disp.h>
  #include <sys/exec.h>
  #include <sys/kmem.h>
  #include <sys/note.h>
  #include <sys/sdt.h>
+ #include <sys/brand.h>
  
  /*
   * This is the loadable module wrapper.
   */
  #include <sys/modctl.h>
  
  extern int intpexec(struct vnode *, struct execa *, struct uarg *,
!     struct intpdata *, int, long *, int, caddr_t, struct cred *, int *);
  
  static struct execsw esw = {
          intpmagicstr,
          0,
          2,
*** 124,140 ****
                  return (ENOEXEC);
          ASSERT(*cp == '\n');
          *cp = '\0';
  
          /*
!          * Locate the beginning and end of the interpreter name.
!          * In addition to the name, one additional argument may
!          * optionally be included here, to be prepended to the
!          * arguments provided on the command line.  Thus, for
!          * example, you can say
           *
           *      #! /usr/bin/awk -f
           */
          for (cp = &linep[2]; *cp == ' '; cp++)
                  ;
          if (*cp == '\0')
                  return (ENOEXEC);
--- 126,149 ----
                  return (ENOEXEC);
          ASSERT(*cp == '\n');
          *cp = '\0';
  
          /*
!          * Locate the beginning and end of the interpreter name. Historically,
!          * for illumos and its predecessors, in addition to the name, one
!          * additional argument may optionally be included here, to be prepended
!          * to the arguments provided on the command line. Thus, for example,
!          * you can say
           *
           *      #! /usr/bin/awk -f
+          *
+          * However, handling of interpreter arguments varies across operating
+          * systems and other systems allow more than one argument. In
+          * particular, Linux allows more than one and delivers all arguments
+          * as a single string (argv[1] is "-arg1 -arg2 ..."). We support this
+          * style of argument handling as a brand-specific option (setting
+          * b_intp_parse_arg to B_FALSE).
           */
          for (cp = &linep[2]; *cp == ' '; cp++)
                  ;
          if (*cp == '\0')
                  return (ENOEXEC);
*** 149,163 ****
--- 158,175 ----
                          cp++;
                  if (*cp == '\0')
                          idatap->intp_arg[0] = NULL;
                  else {
                          idatap->intp_arg[0] = cp;
+                         if (!PROC_IS_BRANDED(curproc) ||
+                             BROP(curproc)->b_intp_parse_arg) {
                                  while (*cp && *cp != ' ')
                                          cp++;
                                  *cp = '\0';
                          }
                  }
+         }
          return (0);
  }
  
  /*
   * We support nested interpreters up to a depth of INTP_MAXDEPTH (this value
*** 186,198 ****
          int level,
          long *execsz,
          int setid,
          caddr_t exec_file,
          struct cred *cred,
!         int brand_action)
  {
-         _NOTE(ARGUNUSED(brand_action))
          vnode_t *nvp;
          int error = 0;
          struct intpdata idata;
          struct pathname intppn;
          struct pathname resolvepn;
--- 198,209 ----
          int level,
          long *execsz,
          int setid,
          caddr_t exec_file,
          struct cred *cred,
!         int *brand_action)
  {
          vnode_t *nvp;
          int error = 0;
          struct intpdata idata;
          struct pathname intppn;
          struct pathname resolvepn;
*** 279,289 ****
                  numtos(fd, &devfd[8]);
                  args->fname = devfd;
          }
  
          error = gexec(&nvp, uap, args, &idata, ++level, execsz, exec_file, cred,
!             EBA_NONE);
  
          if (!error) {
                  /*
                   * Close this executable as the interpreter
                   * will open and close it later on.
--- 290,300 ----
                  numtos(fd, &devfd[8]);
                  args->fname = devfd;
          }
  
          error = gexec(&nvp, uap, args, &idata, ++level, execsz, exec_file, cred,
!             brand_action);
  
          if (!error) {
                  /*
                   * Close this executable as the interpreter
                   * will open and close it later on.