Merge "Revert "Switch back to the BSD exec for now.""
diff --git a/libc/bionic/exec.cpp b/libc/bionic/exec.cpp
index 354f931..c43eb90 100644
--- a/libc/bionic/exec.cpp
+++ b/libc/bionic/exec.cpp
@@ -115,7 +115,8 @@
// If it's an absolute or relative path name, it's easy.
if (strchr(name, '/') && execve(name, argv, envp) == -1) {
- return __exec_as_script(name, argv, envp);
+ if (errno == ENOEXEC) return __exec_as_script(name, argv, envp);
+ return -1;
}
// Get the path we're searching.
diff --git a/linker/linker.cpp b/linker/linker.cpp
index d2a6e7d..033aa8f 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -3394,12 +3394,15 @@
}
}
- const char* executable_path = get_executable_path();
struct stat file_stat;
- if (TEMP_FAILURE_RETRY(stat(executable_path, &file_stat)) != 0) {
- __libc_fatal("unable to stat file for the executable \"%s\": %s", executable_path, strerror(errno));
+ // Stat "/proc/self/exe" instead of executable_path because
+ // the executable could be unlinked by this point and it should
+ // not cause a crash (see http://b/31084669)
+ if (TEMP_FAILURE_RETRY(stat("/proc/self/exe", &file_stat)) != 0) {
+ __libc_fatal("unable to stat \"/proc/self/exe\": %s", strerror(errno));
}
+ const char* executable_path = get_executable_path();
soinfo* si = soinfo_alloc(&g_default_namespace, executable_path, &file_stat, 0, RTLD_GLOBAL);
if (si == nullptr) {
__libc_fatal("Couldn't allocate soinfo: out of memory?");
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 69d1906..6299469 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -1272,3 +1272,12 @@
// implementation.
eth.Run([&]() { execvpe(tf.filename, eth.GetArgs(), eth.GetEnv()); }, 0, "script\n");
}
+
+TEST(UNISTD_TEST, execvp_libcore_test_55017) {
+ ExecTestHelper eth;
+ eth.SetArgs({"/system/bin/does-not-exist", nullptr});
+
+ errno = 0;
+ ASSERT_EQ(-1, execvp("/system/bin/does-not-exist", eth.GetArgs()));
+ ASSERT_EQ(ENOENT, errno);
+}