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,10 +20,11 @@
  */
 /*
  * 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,18 +46,19 @@
 #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);
+    struct intpdata *, int, long *, int, caddr_t, struct cred *, int *);
 
 static struct execsw esw = {
         intpmagicstr,
         0,
         2,
@@ -124,17 +126,24 @@
                 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
+         * 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,15 +158,18 @@
                         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,13 +198,12 @@
         int level,
         long *execsz,
         int setid,
         caddr_t exec_file,
         struct cred *cred,
-        int brand_action)
+        int *brand_action)
 {
-        _NOTE(ARGUNUSED(brand_action))
         vnode_t *nvp;
         int error = 0;
         struct intpdata idata;
         struct pathname intppn;
         struct pathname resolvepn;
@@ -279,11 +290,11 @@
                 numtos(fd, &devfd[8]);
                 args->fname = devfd;
         }
 
         error = gexec(&nvp, uap, args, &idata, ++level, execsz, exec_file, cred,
-            EBA_NONE);
+            brand_action);
 
         if (!error) {
                 /*
                  * Close this executable as the interpreter
                  * will open and close it later on.