Print this page
5798 fexecve() needed per POSIX 2008

@@ -18,10 +18,11 @@
  *
  * CDDL HEADER END
  */
 
 /*
+ * Copyright 2015 Garrett D'Amore <garrett@damore.org>
  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*      Copyright (c) 1988 AT&T */
 /*        All Rights Reserved   */

@@ -96,10 +97,12 @@
 uint_t auxv_hwcap32_2 = 0;      /* 32-bit version of auxv_hwcap2 */
 #endif
 
 #define PSUIDFLAGS              (SNOCD|SUGID)
 
+#define DEVFD                   "/dev/fd/"
+
 /*
  * exece() - system call wrapper around exec_common()
  */
 int
 exece(const char *fname, const char **argp, const char **envp)

@@ -196,11 +199,26 @@
          * there are other cases in which that failure may occur.
          */
         if ((error = pn_get((char *)fname, UIO_USERSPACE, &pn)) != 0)
                 goto out;
         pn_alloc(&resolvepn);
-        if ((error = lookuppn(&pn, &resolvepn, FOLLOW, &dir, &vp)) != 0) {
+
+        if (strncmp(pn.pn_path, DEVFD, strlen(DEVFD)) == 0) {
+                /* looks like a /dev/fd node */
+                char *p = pn.pn_path + strlen(DEVFD);
+                int fd = stoi(&p);
+                if ((fd < 0) || (*p != 0) || (p == pn.pn_path)) {
+                        error = EBADF;
+                        goto out;
+                }
+                if ((error = fgetstartvp(fd, NULL, &vp)) != 0) {
+                        goto out;       /* error will be EBADF */
+                }
+                (void) pn_set(&resolvepn, pn.pn_path);
+
+        } else if ((error =
+            lookuppn(&pn, &resolvepn, FOLLOW, &dir, &vp)) != 0) {
                 pn_free(&resolvepn);
                 pn_free(&pn);
                 if (error != EINVAL)
                         goto out;