| // 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 |