blob: 7b4cefe5bd146aa457ff53c4cb65a9fedcbf25d8 [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 "src/devices/bin/driver_manager/system_instance.h"
#include <fidl/fuchsia.kernel/cpp/wire.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/service/llcpp/service.h>
#include <lib/zx/process.h>
#include <lib/zx/resource.h>
#include <lib/zx/time.h>
#include <string>
#include <zxtest/zxtest.h>
#include "lib/fidl/llcpp/connect_service.h"
#include "src/devices/bin/driver_manager/coordinator.h"
#include "src/devices/bin/driver_manager/coordinator_test_utils.h"
#include "src/devices/bin/driver_manager/driver_host.h"
namespace fkernel = fuchsia_kernel;
namespace {
// Get the root job from the root job service.
zx_status_t get_root_job(zx::job* root_job) {
auto client_end = service::Connect<fkernel::RootJob>();
if (client_end.is_error()) {
return client_end.error_value();
}
auto client = fidl::BindSyncClient(std::move(*client_end));
auto result = client->Get();
if (!result.ok()) {
return result.status();
}
*root_job = std::move(result.value().job);
return ZX_OK;
}
class DummyFsProvider : public FsProvider {
public:
~DummyFsProvider() {}
fidl::ClientEnd<fuchsia_io::Directory> CloneFs(const char* path) override {
auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
ZX_ASSERT(endpoints.status_value() == ZX_OK);
return std::move(endpoints->client);
}
};
class SystemInstanceTest : public zxtest::Test {
public:
SystemInstanceTest()
: inspect_manager_(loop_.dispatcher()),
coordinator_(DefaultConfig(nullptr, nullptr, nullptr), &inspect_manager_,
loop_.dispatcher(), loop_.dispatcher()) {}
SystemInstance under_test_;
LoaderServiceConnector service_connector_;
DummyFsProvider fs_provider_;
async::Loop loop_{&kAsyncLoopConfigNoAttachToCurrentThread};
InspectManager inspect_manager_;
Coordinator coordinator_;
};
// Verify the job that driver_hosts are launched under also lacks ZX_POL_AMBIENT_MARK_VMO_EXEC.
TEST_F(SystemInstanceTest, DriverHostJobLacksAmbientVmex) {
zx::job root_job;
ASSERT_OK(get_root_job(&root_job));
zx::job driver_job;
ASSERT_OK(under_test_.CreateDriverHostJob(root_job, &driver_job));
DriverHostConfig config{
.name = "ambient_vmex_test_util",
.binary = "/pkg/bin/ambient_vmex_test_util",
.env = nullptr,
.job = zx::unowned(driver_job),
.root_resource = zx::unowned_resource(),
.loader_service_connector = &service_connector_,
.fs_provider = &fs_provider_,
.coordinator = &coordinator_,
};
fbl::RefPtr<DriverHost> host;
ASSERT_OK(DriverHost::Launch(config, &host));
ASSERT_OK(host->proc()->wait_one(ZX_TASK_TERMINATED, zx::time::infinite(), nullptr));
zx_info_process_t proc_info;
ASSERT_OK(
host->proc()->get_info(ZX_INFO_PROCESS, &proc_info, sizeof(proc_info), nullptr, nullptr));
ASSERT_TRUE(proc_info.flags & ZX_INFO_PROCESS_FLAG_EXITED);
// A return code of 1 from the util process indicates the replace_as_executable call failed with
// ACCESS_DENIED.
ASSERT_EQ(proc_info.return_code, 1);
}
TEST_F(SystemInstanceTest, DriverHostJobLacksNewProcess) {
zx::job root_job;
ASSERT_OK(get_root_job(&root_job));
zx::job driver_job;
ASSERT_OK(under_test_.CreateDriverHostJob(root_job, &driver_job));
DriverHostConfig config{
.name = "new_process_test_util",
.binary = "/pkg/bin/new_process_test_util",
.env = nullptr,
.job = zx::unowned(driver_job),
.root_resource = zx::unowned_resource(),
.loader_service_connector = &service_connector_,
.fs_provider = &fs_provider_,
.coordinator = &coordinator_,
};
fbl::RefPtr<DriverHost> host;
ASSERT_OK(DriverHost::Launch(config, &host));
ASSERT_OK(host->proc()->wait_one(ZX_TASK_TERMINATED, zx::time::infinite(), nullptr));
zx_info_process_t proc_info;
ASSERT_OK(
host->proc()->get_info(ZX_INFO_PROCESS, &proc_info, sizeof(proc_info), nullptr, nullptr));
ASSERT_TRUE(proc_info.flags & ZX_INFO_PROCESS_FLAG_EXITED);
// A return code of 1 from the util process indicates the process_create call failed with
// ACCESS_DENIED.
ASSERT_EQ(proc_info.return_code, 1);
}
} // namespace