From 0204fbd38b729438a8fc2d5586df07141b3a3ea3 Mon Sep 17 00:00:00 2001 From: Joshua Peraza Date: Wed, 29 Aug 2018 07:28:10 -0700 Subject: [PATCH] posix: Make DoubleForkAndExec accept an envp parameter This will be useful to allow setting variables such as CLASSPATH or LD_LIBRARY_PATH without modifying or depending upon the application's current environment. Bug: crashpad:30 Change-Id: I34f31bcc397e51d789b48eb654d80f992a719074 Reviewed-on: https://chromium-review.googlesource.com/1194399 Commit-Queue: Joshua Peraza Reviewed-by: Mark Mentovai --- client/crashpad_client_linux.cc | 2 +- client/crashpad_client_mac.cc | 1 + util/posix/double_fork_and_exec.cc | 19 +++++++++++++++++++ util/posix/double_fork_and_exec.h | 7 +++++++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/client/crashpad_client_linux.cc b/client/crashpad_client_linux.cc index 6a7c638c..ec5396f3 100644 --- a/client/crashpad_client_linux.cc +++ b/client/crashpad_client_linux.cc @@ -201,7 +201,7 @@ bool CrashpadClient::StartHandlerForClient( argv.push_back(FormatArgumentInt("initial-client-fd", socket)); - return DoubleForkAndExec(argv, socket, true, nullptr); + return DoubleForkAndExec(argv, nullptr, socket, true, nullptr); } // static diff --git a/client/crashpad_client_mac.cc b/client/crashpad_client_mac.cc index 4a408206..22bd538c 100644 --- a/client/crashpad_client_mac.cc +++ b/client/crashpad_client_mac.cc @@ -338,6 +338,7 @@ class HandlerStarter final : public NotifyServer::DefaultInterface { // this interface. if (!DoubleForkAndExec( argv, + nullptr, server_write_fd.get(), true, restart ? CrashpadClient::UseSystemDefaultHandler : nullptr)) { diff --git a/util/posix/double_fork_and_exec.cc b/util/posix/double_fork_and_exec.cc index df74f709..e4ad9988 100644 --- a/util/posix/double_fork_and_exec.cc +++ b/util/posix/double_fork_and_exec.cc @@ -27,9 +27,12 @@ namespace crashpad { bool DoubleForkAndExec(const std::vector& argv, + const std::vector* envp, int preserve_fd, bool use_path, void (*child_function)()) { + DCHECK(!envp || !use_path); + // argv_c contains const char* pointers and is terminated by nullptr. This is // suitable for passing to execv(). Although argv_c is not used in the parent // process, it must be built in the parent process because it’s unsafe to do @@ -41,6 +44,15 @@ bool DoubleForkAndExec(const std::vector& argv, } argv_c.push_back(nullptr); + std::vector envp_c; + if (envp) { + envp_c.reserve(envp->size() + 1); + for (const std::string& variable : *envp) { + envp_c.push_back(variable.c_str()); + } + envp_c.push_back(nullptr); + } + // Double-fork(). The three processes involved are parent, child, and // grandchild. The grandchild will call execv(). The child exits immediately // after spawning the grandchild, so the grandchild becomes an orphan and its @@ -102,6 +114,13 @@ bool DoubleForkAndExec(const std::vector& argv, // const_cast is safe. char* const* argv_for_execv = const_cast(&argv_c[0]); + if (envp) { + // This cast is safe for the same reason that the argv_for_execv cast is. + char* const* envp_for_execv = const_cast(&envp_c[0]); + execve(argv_for_execv[0], argv_for_execv, envp_for_execv); + PLOG(FATAL) << "execve " << argv_for_execv[0]; + } + if (use_path) { execvp(argv_for_execv[0], argv_for_execv); PLOG(FATAL) << "execvp " << argv_for_execv[0]; diff --git a/util/posix/double_fork_and_exec.h b/util/posix/double_fork_and_exec.h index df340d07..02fc0f28 100644 --- a/util/posix/double_fork_and_exec.h +++ b/util/posix/double_fork_and_exec.h @@ -36,6 +36,9 @@ namespace crashpad { //! //! \param[in] argv The argument vector to start the grandchild process with. //! `argv[0]` is used as the path to the executable. +//! \param[in] envp A vector of environment variables of the form `var=value` to +//! be passed to `execve()`. If this value is `nullptr`, the current +//! environment is used. //! \param[in] preserve_fd A file descriptor to be inherited by the grandchild //! process. This file descriptor is inherited in addition to the three file //! descriptors associated with the standard input/output streams. Use `-1` @@ -49,6 +52,9 @@ namespace crashpad { //! that this function will run in the context of a forked process, and must //! be safe for that purpose. //! +//! Setting both \a envp to a value other than `nullptr` and \a use_path to +//! `true` is not currently supported. +//! //! \return `true` on success, and `false` on failure with a message logged. //! Only failures that occur in the parent process that indicate a definite //! failure to start the the grandchild are reported in the return value. @@ -58,6 +64,7 @@ namespace crashpad { //! failures, for example, by observing a failure to perform a successful //! handshake with the grandchild process. bool DoubleForkAndExec(const std::vector& argv, + const std::vector* envp, int preserve_fd, bool use_path, void (*child_function)());