Commit 0629d40f authored by Wez's avatar Wez Committed by Commit Bot

Reimplement base::LaunchProcess using the fdio_spawn_etc() API.

LaunchProcess was previously implemented using "launchpad", which is
being replaced for SDK users by the fdio_spawn*() APIs.

- Migrate call-sites off the old |options.clone_flags|.
- Add the fdio_spawn*() header file to our GN package rule for "fdio".
- Add TODO to "launchpad" package definition for it to be removed once
  all dependency repos have been updated (e.g. gtest, crashpad).

Bug: 848028
Change-Id: I2d871a0f77bd9cba0d16217371069989fdef17f3
Reviewed-on: https://chromium-review.googlesource.com/1081078Reviewed-by: default avatarGabriel Charette <gab@chromium.org>
Reviewed-by: default avatarSergey Ulanov <sergeyu@chromium.org>
Commit-Queue: Wez <wez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#564731}
parent 604e543e
......@@ -1400,12 +1400,11 @@ jumbo_component("base") {
# TODO(https://crbug.com/841171): Move these back to |deps|.
public_deps += [
"//third_party/fuchsia-sdk:async",
"//third_party/fuchsia-sdk:launchpad",
"//third_party/fuchsia-sdk:fdio",
]
deps += [
"//third_party/fuchsia-sdk:async_default",
"//third_party/fuchsia-sdk:fdio",
"//third_party/fuchsia-sdk:fidl",
"//third_party/fuchsia-sdk:svc",
"//third_party/fuchsia-sdk:zx",
......
......@@ -24,7 +24,7 @@ struct ScopedZxHandleTraits {
static zx_handle_t InvalidValue() { return ZX_HANDLE_INVALID; }
static void Free(zx_handle_t object) {
zx_status_t status = zx_handle_close(object);
ZX_CHECK(status == ZX_OK, status) << "zx_handle_close";
ZX_CHECK(status == ZX_OK, status) << "zx_handle_close: " << object;
}
};
......
......@@ -24,7 +24,7 @@
#if defined(OS_WIN)
#include <windows.h>
#elif defined(OS_FUCHSIA)
#include <launchpad/launchpad.h>
#include <fdio/spawn.h>
#include <zircon/types.h>
#endif
......@@ -187,28 +187,23 @@ struct BASE_EXPORT LaunchOptions {
zx_handle_t job_handle = ZX_HANDLE_INVALID;
// Specifies additional handles to transfer (not duplicate) to the child
// process. The handles remain valid in this process if launch fails.
// Each entry is an <id,handle> pair, with an |id| created using the PA_HND()
// macro. The child retrieves the handle |zx_get_startup_handle(id)|.
// process. Each entry is an <id,handle> pair, with an |id| created using the
// PA_HND() macro. The child retrieves the handle |zx_get_startup_handle(id)|.
// The supplied handles are consumed by LaunchProcess() even on failure.
HandlesToTransferVector handles_to_transfer;
// If set, specifies which capabilities should be granted (cloned) to the
// child process.
// A zero value indicates that the child process will receive
// no capabilities.
// By default the child will inherit the same capabilities, job, and CWD
// from the parent process.
uint32_t clone_flags =
LP_CLONE_FDIO_NAMESPACE | LP_CLONE_DEFAULT_JOB | LP_CLONE_FDIO_STDIO;
// Specifies the namespace paths which are to be cloned in the child process'
// namespace. If left unset, the child process will be launched with an empty
// namespace.
// This flag allows the parent to pass only the bare minimum OS capabilities
// to the child process, so that the potential attack surface is reduced in
// case child process is compromised.
// Cannot be combined with the clone flag LP_CLONE_FDIO_NAMESPACE, which is
// equivalent to cloning every path.
// Specifies which basic capabilities to grant to the child process.
// By default the child process will receive the caller's complete namespace,
// access to the current base::fuchsia::DefaultJob(), handles for stdio and
// access to the dynamic library loader.
// Note that the child is always provided access to the loader service.
uint32_t spawn_flags = FDIO_SPAWN_CLONE_NAMESPACE | FDIO_SPAWN_CLONE_STDIO |
FDIO_SPAWN_CLONE_JOB;
// Specifies paths to clone from the calling process' namespace into that of
// the child process. If |paths_to_map| is empty then the process will receive
// either a full copy of the parent's namespace, or an empty one, depending on
// whether FDIO_SPAWN_CLONE_NAMESPACE is set.
std::vector<FilePath> paths_to_map;
#endif // defined(OS_FUCHSIA)
......
This diff is collapsed.
......@@ -248,7 +248,7 @@ TEST_F(ProcessUtilTest, SelectivelyClonedDir) {
LaunchOptions options;
options.paths_to_map.push_back(base::FilePath("/tmp"));
options.clone_flags = LP_CLONE_FDIO_STDIO;
options.spawn_flags = FDIO_SPAWN_CLONE_STDIO;
Process process(SpawnChildWithOptions("CheckTmpFileExists", options));
ASSERT_TRUE(process.IsValid());
......@@ -271,7 +271,7 @@ TEST_F(ProcessUtilTest, CloneAlternateDir) {
LaunchOptions options;
options.paths_to_map.push_back(base::FilePath("/tmp"));
options.paths_to_map.push_back(base::FilePath("/data"));
options.clone_flags = LP_CLONE_FDIO_STDIO;
options.spawn_flags = FDIO_SPAWN_CLONE_STDIO;
Process process(SpawnChildWithOptions("CheckTmpFileExists", options));
ASSERT_TRUE(process.IsValid());
......@@ -283,6 +283,54 @@ TEST_F(ProcessUtilTest, CloneAlternateDir) {
EXPECT_EQ(1, exit_code);
}
TEST_F(ProcessUtilTest, HandlesToTransferClosedOnSpawnFailure) {
ScopedZxHandle handles[2];
zx_status_t result =
zx_channel_create(0, handles[0].receive(), handles[1].receive());
ZX_CHECK(ZX_OK == result, result) << "zx_channel_create";
LaunchOptions options;
options.handles_to_transfer.push_back({0, handles[0].get()});
// Launch a non-existent binary, causing fdio_spawn() to fail.
CommandLine command_line(FilePath(
FILE_PATH_LITERAL("💩magical_filename_that_will_never_exist_ever")));
Process process(LaunchProcess(command_line, options));
ASSERT_FALSE(process.IsValid());
// If LaunchProcess did its job then handles[0] is no longer valid, and
// handles[1] should observe a channel-closed signal.
EXPECT_EQ(
zx_object_wait_one(handles[1].get(), ZX_CHANNEL_PEER_CLOSED, 0, nullptr),
ZX_OK);
EXPECT_EQ(ZX_ERR_BAD_HANDLE, zx_handle_close(handles[0].get()));
ignore_result(handles[0].release());
}
TEST_F(ProcessUtilTest, HandlesToTransferClosedOnBadPathToMapFailure) {
ScopedZxHandle handles[2];
zx_status_t result =
zx_channel_create(0, handles[0].receive(), handles[1].receive());
ZX_CHECK(ZX_OK == result, result) << "zx_channel_create";
LaunchOptions options;
options.handles_to_transfer.push_back({0, handles[0].get()});
options.spawn_flags = options.spawn_flags & ~FDIO_SPAWN_CLONE_NAMESPACE;
options.paths_to_map.emplace_back("💩magical_path_that_will_never_exist_ever");
// LaunchProces should fail to open() the path_to_map, and fail before
// fdio_spawn().
Process process(LaunchProcess(CommandLine(FilePath()), options));
ASSERT_FALSE(process.IsValid());
// If LaunchProcess did its job then handles[0] is no longer valid, and
// handles[1] should observe a channel-closed signal.
EXPECT_EQ(
zx_object_wait_one(handles[1].get(), ZX_CHANNEL_PEER_CLOSED, 0, nullptr),
ZX_OK);
EXPECT_EQ(ZX_ERR_BAD_HANDLE, zx_handle_close(handles[0].get()));
ignore_result(handles[0].release());
}
#endif // defined(OS_FUCHSIA)
// On Android SpawnProcess() doesn't use LaunchProcess() and doesn't support
......
......@@ -37,13 +37,13 @@ void UpdateLaunchOptionsForSandbox(service_manager::SandboxType type,
options->clear_environ = true;
// Propagate stdout/stderr/stdin to the child.
options->clone_flags = LP_CLONE_FDIO_STDIO;
options->spawn_flags = FDIO_SPAWN_CLONE_STDIO;
return;
}
DCHECK_EQ(type, service_manager::SANDBOX_TYPE_NO_SANDBOX);
options->clone_flags =
LP_CLONE_FDIO_NAMESPACE | LP_CLONE_DEFAULT_JOB | LP_CLONE_FDIO_STDIO;
options->spawn_flags = FDIO_SPAWN_CLONE_NAMESPACE | FDIO_SPAWN_CLONE_JOB |
FDIO_SPAWN_CLONE_STDIO;
options->clear_environ = false;
}
......
......@@ -44,6 +44,7 @@ fuchsia_sdk_pkg("fdio") {
"include/fdio/private.h",
"include/fdio/remoteio.h",
"include/fdio/socket.h",
"include/fdio/spawn.h",
"include/fdio/util.h",
"include/fdio/vfs.h",
"include/fdio/watcher.h",
......@@ -192,6 +193,7 @@ fuchsia_sdk_fidl_pkg("input") {
]
}
# TODO(https://crbug.com/848028): Remove this once no dependencies need it.
fuchsia_sdk_pkg("launchpad") {
sources = [
"include/launchpad/launchpad.h",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment