Use posix_spawn instead of vfork
Also correct usage of posix_spawn
Bug: 126128460
Test: built, flashed, booted
system/netd/tests/runtests.sh pass
manual test with remove dnsmasq, netd works fine
Change-Id: Id48c7bf9c02ea27d3a4602efa3913785c0d5c87f
diff --git a/server/TetherController.cpp b/server/TetherController.cpp
index daa07b4..4fc603a 100644
--- a/server/TetherController.cpp
+++ b/server/TetherController.cpp
@@ -18,6 +18,7 @@
#include <fcntl.h>
#include <inttypes.h>
#include <netdb.h>
+#include <spawn.h>
#include <string.h>
#include <sys/socket.h>
@@ -113,25 +114,20 @@
return !strcmp(BP_TOOLS_MODE, bootmode);
}
-pid_t vfork_and_exec(const char* path, char* const argv[], int pipefd[2]) {
- auto pid = vfork();
- if (pid) {
- // Parent process, or vfork() failed. Let caller deal with it.
- return pid;
+int setPosixSpawnFileActionsAddDup2(posix_spawn_file_actions_t* fa, int fd, int new_fd) {
+ int res = posix_spawn_file_actions_init(fa);
+ if (res) {
+ return res;
}
+ return posix_spawn_file_actions_adddup2(fa, fd, new_fd);
+}
- // Don't modify any memory between vfork and execv.
- // Changing state of file descriptors would be fine.
- // dup2 creates fd without CLOEXEC, dnsmasq will receive commands through the
- // duplicated fd.
- if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) {
- // dup2 failed
- _exit(EXIT_FAILURE);
+int setPosixSpawnAttrFlags(posix_spawnattr_t* attr, short flags) {
+ int res = posix_spawnattr_init(attr);
+ if (res) {
+ return res;
}
- execv(path, argv);
- // Should never get here!
- _exit(EXIT_FAILURE);
- return pid;
+ return posix_spawnattr_setflags(attr, flags);
}
} // namespace
@@ -264,16 +260,36 @@
* TODO: Create a monitoring thread to handle and restart
* the daemon if it exits prematurely
*/
- pid_t pid = vfork_and_exec(args[0], args, pipefd);
- int res = errno;
- close(pipefd[0]);
- free(args);
- if (pid < 0) {
- ALOGE("vfork & exec failed (%s)", strerror(errno));
- close(pipefd[1]);
+
+ // Note that don't modify any memory between vfork and execv.
+ // Changing state of file descriptors would be fine. See posix_spawn_file_actions_add*
+ // dup2 creates fd without CLOEXEC, dnsmasq will receive commands through the
+ // duplicated fd.
+ posix_spawn_file_actions_t fa;
+ int res = setPosixSpawnFileActionsAddDup2(&fa, pipefd[0], STDIN_FILENO);
+ if (res) {
+ ALOGE("posix_spawn set fa failed (%s)", strerror(res));
return -res;
}
+ posix_spawnattr_t attr;
+ res = setPosixSpawnAttrFlags(&attr, POSIX_SPAWN_USEVFORK);
+ if (res) {
+ ALOGE("posix_spawn set attr flag failed (%s)", strerror(res));
+ return -res;
+ }
+
+ pid_t pid;
+ res = posix_spawn(&pid, args[0], &fa, &attr, args, nullptr);
+ close(pipefd[0]);
+ free(args);
+ posix_spawnattr_destroy(&attr);
+ posix_spawn_file_actions_destroy(&fa);
+ if (res) {
+ ALOGE("posix_spawn failed (%s)", strerror(res));
+ close(pipefd[1]);
+ return -res;
+ }
mDaemonPid = pid;
mDaemonFd = pipefd[1];
configureForTethering(true);