blob: a2a6b095c13d046b6b47657b072135a82fe03866 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <limits.h>
#include <memory>
#include <cstddef>
#include <cstdint>
#include <fcntl.h>
#include <stdio.h>
#include <fbl/algorithm.h>
#include <fbl/auto_call.h>
#include <fbl/unique_fd.h>
#include <lib/fdio/io.h>
#include <lib/fdio/spawn.h>
#include <lib/zx/job.h>
#include <lib/zx/process.h>
#include <unittest/unittest.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/policy.h>
#include <string>
#include <utility>
namespace {
// Launches handle_policy_test_app with a strict ZX_POL_BAD_HANDLE policy, such that the app would
// crash if an invalid handle was closed (e.g. double-closing).
bool LaunchHelper(const char* argv[]) {
BEGIN_HELPER;
const char* path = argv[0];
fbl::unique_fd fds[2];
int temp_fds[2] = {-1, -1};
ASSERT_EQ(pipe(temp_fds), 0);
fds[0].reset(temp_fds[0]);
fds[1].reset(temp_fds[1]);
fdio_spawn_action_t fdio_actions[3] = {
fdio_spawn_action {
.action = FDIO_SPAWN_ACTION_SET_NAME,
.name = {
.data = path
}
},
fdio_spawn_action {
.action = FDIO_SPAWN_ACTION_CLONE_FD,
.fd = {
.local_fd = fds[1].get(),
.target_fd = STDOUT_FILENO
}
},
fdio_spawn_action {
.action = FDIO_SPAWN_ACTION_TRANSFER_FD,
.fd = {
.local_fd = fds[1].get(),
.target_fd = STDERR_FILENO
}
},
};
zx_status_t status;
zx::job test_job;
status = zx::job::create(*zx::job::default_job(), 0, &test_job);
ASSERT_EQ(status, ZX_OK);
auto auto_call_kill_job = fbl::MakeAutoCall([&test_job] () { test_job.kill(); });
const char name[] = "handle-policy-test-app";
status = test_job.set_property(ZX_PROP_NAME, name, sizeof(name));
ASSERT_EQ(status, ZX_OK);
static const zx_policy_basic_t policy[] = {
zx_policy_basic_t {
.condition = ZX_POL_BAD_HANDLE,
.policy = ZX_POL_ACTION_ALLOW_EXCEPTION
},
};
status = test_job.set_policy(ZX_JOB_POL_RELATIVE, ZX_JOB_POL_BASIC, &policy,
fbl::count_of(policy));
ASSERT_EQ(status, ZX_OK);
fds[1].release(); // To avoid double close since fdio_spawn_etc() closes it.
zx::process process;
char err_msg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
status = fdio_spawn_etc(test_job.get(), FDIO_SPAWN_CLONE_ALL,
argv[0], argv, nullptr,
fbl::count_of(fdio_actions), fdio_actions,
process.reset_and_get_address(), err_msg);
ASSERT_EQ(status, ZX_OK);
// Pipe through output.
char buf[1024];
ssize_t bytes_read = 0;
while ((bytes_read = read(fds[0].get(), buf, sizeof(buf))) > 0) {
fwrite(buf, 1, bytes_read, stdout);
}
status = process.wait_one(ZX_PROCESS_TERMINATED, zx::time::infinite(), nullptr);
ASSERT_EQ(status, ZX_OK);
// Read the return code.
zx_info_process_t proc_info;
status = process.get_info(ZX_INFO_PROCESS, &proc_info, sizeof(proc_info),
nullptr, nullptr);
ASSERT_EQ(status, ZX_OK);
ASSERT_EQ(proc_info.return_code, 0);
END_HELPER;
}
bool TestWithStrictHandlePolicy() {
BEGIN_TEST;
// This test app contains a subset of fidl-tests; refer to BUILD.gn
const char* root_dir = getenv("TEST_ROOT_DIR");
if (root_dir == nullptr) {
root_dir = "";
}
const std::string test_app =
std::string(root_dir) + "/bin/fidl-handle-policy-test-app";
const char* args[] = {
test_app.c_str(),
nullptr
};
ASSERT_TRUE(LaunchHelper(args));
END_TEST;
}
} // namespace
BEGIN_TEST_CASE(handle_policy)
RUN_TEST(TestWithStrictHandlePolicy)
END_TEST_CASE(handle_policy)