Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(644)

Unified Diff: chrome/app/chrome_exe_main_mac.cc

Issue 2891933005: Plumb sandbox rules through the helper executable. (Closed)
Patch Set: Cleanup next round of feedback Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/app/chrome_exe_main_mac.c ('k') | sandbox/mac/sandbox_mac_seatbelt_exec_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/app/chrome_exe_main_mac.cc
diff --git a/chrome/app/chrome_exe_main_mac.cc b/chrome/app/chrome_exe_main_mac.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e6365f3f4bd97e4e3befc10e6d7b4ea4b39aa11f
--- /dev/null
+++ b/chrome/app/chrome_exe_main_mac.cc
@@ -0,0 +1,160 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// The entry point for all Mac Chromium processes, including the outer app
+// bundle (browser) and helper app (renderer, plugin, and friends).
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <libgen.h>
+#include <mach-o/dyld.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <string>
+#include <vector>
+
+#include "chrome/common/chrome_version.h"
+
+#if defined(HELPER_EXECUTABLE)
+#include "sandbox/mac/seatbelt_exec.h"
+#endif // defined(HELPER_EXECUTABLE)
+
+namespace {
+
+typedef int (*ChromeMainPtr)(int, char**);
+
+#if defined(HELPER_EXECUTABLE)
+// The name of the parameter containing the executable path.
+constexpr char exec_param[] = "EXECUTABLE_PATH";
Mark Mentovai 2017/05/24 20:42:42 Not really necessary for this to be out here, it c
Greg K 2017/05/25 17:52:05 Done.
+// The name of the parameter containing the PID of Chrome.
+constexpr char pid_param[] = "CHROMIUM_PID";
+// The command line parameter to engage the v2 sandbox.
+constexpr char v2_sandbox_arg[] = "--v2-sandbox";
+// The command line parameter for the file descriptor used to receive the
+// sandbox policy.
+constexpr char fd_mapping_arg[] = "--fd_mapping=";
+
+void SandboxExec(const char* exec_path,
Mark Mentovai 2017/05/24 20:42:41 Now you can make this __attribute__((noreturn)) wh
Greg K 2017/05/25 17:52:05 Done.
+ int argc,
+ char* argv[],
+ int fd_mapping) {
+ char rp[MAXPATHLEN];
+ if (realpath(argv[0], rp) == NULL)
Mark Mentovai 2017/05/24 20:42:41 Should we be using argv[0] or exec_path?
Greg K 2017/05/25 17:52:05 Done.
+ abort();
Mark Mentovai 2017/05/24 20:42:41 Did you want to perror() before abort() for things
Greg K 2017/05/25 17:52:05 Done.
+
+ sandbox::SeatbeltExecServer server(fd_mapping);
+
+ if (!server.SetParameter(exec_param, rp) ||
+ !server.SetParameter(pid_param, std::to_string(getpid()))) {
+ fprintf(stderr, "Failed to set up parameters for sandbox.\n");
+ abort();
+ }
+
+ if (server.InitializeSandbox() != 0)
+ abort();
Mark Mentovai 2017/05/24 20:42:41 And perhaps fprintf(stderr) something for things t
Greg K 2017/05/25 17:52:05 Done.
+
+ std::vector<char*> new_argv;
+ for (int i = 1; i < argc; ++i) {
+ if (strcmp(argv[i], v2_sandbox_arg) != 0 &&
+ strncmp(argv[i], fd_mapping_arg, strlen(fd_mapping_arg)) != 0) {
+ new_argv.push_back(argv[i]);
+ }
+ }
+ new_argv.push_back(nullptr);
+
+ // The helper executable re-executes itself under the sandbox.
+ execv(exec_path, new_argv.data());
+ perror("execve");
+ abort();
+}
+#endif // defined(HELPER_EXECUTABLE)
+
+} // namespace
+
+__attribute__((visibility("default"))) int main(int argc, char* argv[]) {
+ uint32_t exec_path_size = 0;
+ int rv = _NSGetExecutablePath(NULL, &exec_path_size);
+ if (rv != -1) {
+ fprintf(stderr, "_NSGetExecutablePath: get length failed\n");
+ abort();
+ }
+
+ char* exec_path = new char[exec_path_size];
+ rv = _NSGetExecutablePath(exec_path, &exec_path_size);
+ if (rv != 0) {
+ fprintf(stderr, "_NSGetExecutablePath: get path failed\n");
+ abort();
+ }
+
+#if defined(HELPER_EXECUTABLE)
+ bool enable_v2_sandbox = false;
+ int fd_mapping = -1;
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], v2_sandbox_arg) == 0) {
+ enable_v2_sandbox = true;
+ } else if (strncmp(argv[i], fd_mapping_arg, strlen(fd_mapping_arg)) == 0) {
+ // Parse --fd_mapping=X to get the file descriptor X.
+ std::string arg(argv[i]);
+ std::string fd_str = arg.substr(strlen(fd_mapping_arg), arg.length());
+ fd_mapping = std::stoi(fd_str);
+ }
+ }
+ if (enable_v2_sandbox && fd_mapping == -1) {
+ fprintf(stderr, "Must pass a valid file descriptor to --fd_mapping.\n");
+ abort();
+ }
+
+ // SandboxExec either aborts or execs, but there is no return.
+ if (enable_v2_sandbox)
+ SandboxExec(exec_path, argc, argv, fd_mapping);
+
+ const char* const rel_path =
+ "../../../" PRODUCT_FULLNAME_STRING
+ " Framework.framework/" PRODUCT_FULLNAME_STRING " Framework";
+#else
+ const char* const rel_path =
+ "../Versions/" CHROME_VERSION_STRING "/" PRODUCT_FULLNAME_STRING
+ " Framework.framework/" PRODUCT_FULLNAME_STRING " Framework";
+#endif // defined(HELPER_EXECUTABLE)
+
+ // Slice off the last part of the main executable path, and append the
+ // version framework information.
+ const char* parent_dir = dirname(exec_path);
+ if (!parent_dir) {
+ fprintf(stderr, "dirname %s: %s\n", exec_path, strerror(errno));
+ abort();
+ }
+ delete[] exec_path;
+
+ const size_t parent_path_len = strlen(parent_dir);
Mark Mentovai 2017/05/24 20:42:41 parent_dir_len instead of parent_path_len to make
Greg K 2017/05/25 17:52:05 Done.
+ const size_t rel_path_len = strlen(rel_path);
+ // 2 accounts for a trailing NUL byte and the '/' in the middle of the paths.
+ const size_t framework_path_size = parent_path_len + rel_path_len + 2;
+ char* framework_path = new char[framework_path_size];
+ snprintf(framework_path, framework_path_size, "%s/%s", parent_dir, rel_path);
+
+ void* library = dlopen(framework_path, RTLD_LAZY | RTLD_LOCAL | RTLD_FIRST);
+ if (!library) {
+ fprintf(stderr, "dlopen %s: %s\n", framework_path, dlerror());
+ abort();
+ }
+ delete[] framework_path;
+
+ const ChromeMainPtr chrome_main =
+ reinterpret_cast<ChromeMainPtr>(dlsym(library, "ChromeMain"));
+ if (!chrome_main) {
+ fprintf(stderr, "dlsym ChromeMain: %s\n", dlerror());
+ abort();
+ }
+ rv = chrome_main(argc, argv);
+
+ // exit, don't return from main, to avoid the apparent removal of main from
+ // stack backtraces under tail call optimization.
+ exit(rv);
+}
« no previous file with comments | « chrome/app/chrome_exe_main_mac.c ('k') | sandbox/mac/sandbox_mac_seatbelt_exec_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698