[前][次][番号順一覧][スレッド一覧]

ruby-changes:51534

From: normal <ko1@a...>
Date: Mon, 25 Jun 2018 10:06:21 +0900 (JST)
Subject: [ruby-changes:51534] normal:r63744 (trunk): mjit.c: avoid execvp PATH lookup in vfork-ed child

normal	2018-06-25 10:06:15 +0900 (Mon, 25 Jun 2018)

  New Revision: 63744

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=63744

  Log:
    mjit.c: avoid execvp PATH lookup in vfork-ed child
    
    execvp(3) is not async-signal-safe and may alter libc internal
    states (e.g. those used by malloc).  However execv(3) is
    async-signal-safe as of POSIX.1-2008.
    
    So perform the PATH lookup in the parent and use execv(3)
    in the child.

  Modified files:
    trunk/mjit.c
Index: mjit.c
===================================================================
--- mjit.c	(revision 63743)
+++ mjit.c	(revision 63744)
@@ -95,6 +95,15 @@ https://github.com/ruby/ruby/blob/trunk/mjit.c#L95
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
 #endif
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#include "dln.h"
+
+#ifndef MAXPATHLEN
+#  define MAXPATHLEN 1024
+#endif
 
 extern void rb_native_mutex_lock(rb_nativethread_lock_t *lock);
 extern void rb_native_mutex_unlock(rb_nativethread_lock_t *lock);
@@ -349,8 +358,19 @@ start_process(const char *path, char *co https://github.com/ruby/ruby/blob/trunk/mjit.c#L358
     pid = spawnvp(_P_NOWAIT, path, argv);
 #else
     {
-        /* Not calling IO functions between fork and exec for safety */
-        int dev_null = rb_cloexec_open(ruby_null_device, O_WRONLY, 0);
+        /*
+         * Not calling non-async-signal-safe functions between vfork
+         * and execv for safety
+         */
+        char fbuf[MAXPATHLEN];
+        const char *abspath = dln_find_exe_r(path, 0, fbuf, sizeof(fbuf));
+        int dev_null;
+
+        if (!abspath) {
+            fprintf(stderr, "failed to find `%s' in PATH\n", path);
+            return -1;
+        }
+        dev_null = rb_cloexec_open(ruby_null_device, O_WRONLY, 0);
 
         if ((pid = vfork()) == 0) {
             umask(0077);
@@ -362,11 +382,11 @@ start_process(const char *path, char *co https://github.com/ruby/ruby/blob/trunk/mjit.c#L382
                 dup2(dev_null, STDOUT_FILENO);
             }
             (void)close(dev_null);
-            pid = execvp(path, argv); /* Pid will be negative on an error */
+            pid = execv(abspath, argv); /* Pid will be negative on an error */
             /* Even if we successfully found CC to compile PCH we still can
              fail with loading the CC in very rare cases for some reasons.
              Stop the forked process in this case.  */
-            verbose(1, "MJIT: Error in execvp: %s\n", path);
+            verbose(1, "MJIT: Error in execv: %s\n", abspath);
             _exit(1);
         }
         (void)close(dev_null);
@@ -1313,9 +1333,6 @@ system_default_tmpdir(void) https://github.com/ruby/ruby/blob/trunk/mjit.c#L1333
         return tmpdir;
     }
 #elif defined _CS_DARWIN_USER_TEMP_DIR
-    #ifndef MAXPATHLEN
-    #define MAXPATHLEN 1024
-    #endif
     char path[MAXPATHLEN];
     size_t len = confstr(_CS_DARWIN_USER_TEMP_DIR, path, sizeof(path));
     if (len > 0) {

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]