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>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/exec/intp/intp.c
          +++ new/usr/src/uts/common/exec/intp/intp.c
↓ open down ↓ 14 lines elided ↑ open up ↑
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   * Copyright 2012 Milan Jurik. All rights reserved.
       25 + * Copyright 2016, Joyent, Inc.
  25   26   */
  26   27  
  27   28  /*      Copyright (c) 1988 AT&T */
  28   29  /*        All Rights Reserved   */
  29   30  
  30   31  
  31   32  /* from S5R4 1.6 */
  32   33  
  33   34  #include <sys/types.h>
  34   35  #include <sys/param.h>
↓ open down ↓ 5 lines elided ↑ open up ↑
  40   41  #include <sys/vnode.h>
  41   42  #include <sys/proc.h>
  42   43  #include <sys/cmn_err.h>
  43   44  #include <sys/debug.h>
  44   45  #include <sys/pathname.h>
  45   46  #include <sys/disp.h>
  46   47  #include <sys/exec.h>
  47   48  #include <sys/kmem.h>
  48   49  #include <sys/note.h>
  49   50  #include <sys/sdt.h>
       51 +#include <sys/brand.h>
  50   52  
  51   53  /*
  52   54   * This is the loadable module wrapper.
  53   55   */
  54   56  #include <sys/modctl.h>
  55   57  
  56   58  extern int intpexec(struct vnode *, struct execa *, struct uarg *,
  57      -    struct intpdata *, int, long *, int, caddr_t, struct cred *, int);
       59 +    struct intpdata *, int, long *, int, caddr_t, struct cred *, int *);
  58   60  
  59   61  static struct execsw esw = {
  60   62          intpmagicstr,
  61   63          0,
  62   64          2,
  63   65          intpexec,
  64   66          NULL
  65   67  };
  66   68  
  67   69  /*
↓ open down ↓ 51 lines elided ↑ open up ↑
 119  121           */
 120  122          for (cp = &linep[2]; cp < &linep[INTPSZ] && *cp != '\n'; cp++)
 121  123                  if (*cp == '\t')
 122  124                          *cp = ' ';
 123  125          if (cp >= &linep[INTPSZ])
 124  126                  return (ENOEXEC);
 125  127          ASSERT(*cp == '\n');
 126  128          *cp = '\0';
 127  129  
 128  130          /*
 129      -         * Locate the beginning and end of the interpreter name.
 130      -         * In addition to the name, one additional argument may
 131      -         * optionally be included here, to be prepended to the
 132      -         * arguments provided on the command line.  Thus, for
 133      -         * example, you can say
      131 +         * Locate the beginning and end of the interpreter name. Historically,
      132 +         * for illumos and its predecessors, in addition to the name, one
      133 +         * additional argument may optionally be included here, to be prepended
      134 +         * to the arguments provided on the command line. Thus, for example,
      135 +         * you can say
 134  136           *
 135  137           *      #! /usr/bin/awk -f
      138 +         *
      139 +         * However, handling of interpreter arguments varies across operating
      140 +         * systems and other systems allow more than one argument. In
      141 +         * particular, Linux allows more than one and delivers all arguments
      142 +         * as a single string (argv[1] is "-arg1 -arg2 ..."). We support this
      143 +         * style of argument handling as a brand-specific option (setting
      144 +         * b_intp_parse_arg to B_FALSE).
 136  145           */
 137  146          for (cp = &linep[2]; *cp == ' '; cp++)
 138  147                  ;
 139  148          if (*cp == '\0')
 140  149                  return (ENOEXEC);
 141  150          idatap->intp_name[0] = cp;
 142  151          while (*cp && *cp != ' ')
 143  152                  cp++;
 144  153          if (*cp == '\0') {
 145  154                  idatap->intp_arg[0] = NULL;
 146  155          } else {
 147  156                  *cp++ = '\0';
 148  157                  while (*cp == ' ')
 149  158                          cp++;
 150  159                  if (*cp == '\0')
 151  160                          idatap->intp_arg[0] = NULL;
 152  161                  else {
 153  162                          idatap->intp_arg[0] = cp;
 154      -                        while (*cp && *cp != ' ')
 155      -                                cp++;
 156      -                        *cp = '\0';
      163 +                        if (!PROC_IS_BRANDED(curproc) ||
      164 +                            BROP(curproc)->b_intp_parse_arg) {
      165 +                                while (*cp && *cp != ' ')
      166 +                                        cp++;
      167 +                                *cp = '\0';
      168 +                        }
 157  169                  }
 158  170          }
 159  171          return (0);
 160  172  }
 161  173  
 162  174  /*
 163  175   * We support nested interpreters up to a depth of INTP_MAXDEPTH (this value
 164  176   * matches the depth on Linux). When a nested interpreter is in use, the
 165  177   * previous name and argument must be passed along. We use the intpdata_t
 166  178   * name and argument arrays for this. In the normal, non-nested case, only the
↓ open down ↓ 14 lines elided ↑ open up ↑
 181  193  intpexec(
 182  194          struct vnode *vp,
 183  195          struct execa *uap,
 184  196          struct uarg *args,
 185  197          struct intpdata *idatap,
 186  198          int level,
 187  199          long *execsz,
 188  200          int setid,
 189  201          caddr_t exec_file,
 190  202          struct cred *cred,
 191      -        int brand_action)
      203 +        int *brand_action)
 192  204  {
 193      -        _NOTE(ARGUNUSED(brand_action))
 194  205          vnode_t *nvp;
 195  206          int error = 0;
 196  207          struct intpdata idata;
 197  208          struct pathname intppn;
 198  209          struct pathname resolvepn;
 199  210          char *opath;
 200  211          char devfd[19]; /* 32-bit int fits in 10 digits + 8 for "/dev/fd/" */
 201  212          int fd = -1;
 202  213  
 203  214          if (level >= INTP_MAXDEPTH) {   /* Can't recurse past maxdepth */
↓ open down ↓ 70 lines elided ↑ open up ↑
 274  285              (setid & (EXECSETID_UGIDS|EXECSETID_SETID)) ==
 275  286              (EXECSETID_UGIDS|EXECSETID_SETID)) {
 276  287                  (void) strcpy(devfd, "/dev/fd/");
 277  288                  if (error = execopen(&vp, &fd))
 278  289                          goto done;
 279  290                  numtos(fd, &devfd[8]);
 280  291                  args->fname = devfd;
 281  292          }
 282  293  
 283  294          error = gexec(&nvp, uap, args, &idata, ++level, execsz, exec_file, cred,
 284      -            EBA_NONE);
      295 +            brand_action);
 285  296  
 286  297          if (!error) {
 287  298                  /*
 288  299                   * Close this executable as the interpreter
 289  300                   * will open and close it later on.
 290  301                   */
 291  302                  (void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, cred, NULL);
 292  303          }
 293  304  done:
 294  305          VN_RELE(nvp);
 295  306          args->pathname = opath;
 296  307          pn_free(&resolvepn);
 297  308  fail:
 298  309          kmem_free(idata.intp, INTPSZ);
 299  310          if (error && fd != -1)
 300  311                  (void) execclose(fd);
 301  312  bad:
 302  313          return (error);
 303  314  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX