| // Copyright 2020 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 "bind_devfs_to_namespace.h" |
| |
| #include <fuchsia/sys2/cpp/fidl.h> |
| #include <lib/fdio/directory.h> |
| #include <lib/fdio/namespace.h> |
| #include <lib/syslog/cpp/macros.h> |
| #include <zircon/types.h> |
| |
| namespace isolated_devmgr { |
| |
| zx::status<> OneTimeSetUp() { |
| static zx::status<> status = []() -> zx::status<> { |
| // Mark this process as critical so that if this process terminates, all other processes |
| // within this job get terminated (e.g. file system processes). |
| auto status = zx::make_status(zx::job::default_job()->set_critical(0, *zx::process::self())); |
| if (status.is_error()) { |
| FX_LOGS(ERROR) << "Unable to make process critical: " << status.status_string(); |
| return status; |
| } |
| status = isolated_devmgr::BindDevfsToNamespace(); |
| if (status.is_error()) { |
| FX_LOGS(ERROR) << "Unable to bind devfs to namespace: " << status.status_string(); |
| return status; |
| } |
| return zx::ok(); |
| }(); |
| return status; |
| } |
| |
| zx::status<> BindDevfsToNamespace() { |
| fdio_ns_t* name_space; |
| auto status = zx::make_status(fdio_ns_get_installed(&name_space)); |
| if (status.is_error()) { |
| FX_LOGS(ERROR) << "Failed to get namespace: " << status.status_string(); |
| return status; |
| } |
| fidl::SynchronousInterfacePtr<fuchsia::sys2::Realm> realm; |
| std::string service_name = std::string("/svc/") + fuchsia::sys2::Realm::Name_; |
| status = zx::make_status( |
| fdio_service_connect(service_name.c_str(), realm.NewRequest().TakeChannel().get())); |
| if (status.is_error()) { |
| FX_LOGS(ERROR) << "Unable to connect to realm service: " << status.status_string(); |
| return status; |
| } |
| fidl::SynchronousInterfacePtr<fuchsia::io::Directory> exposed_dir; |
| fuchsia::sys2::Realm_BindChild_Result result; |
| status = zx::make_status(realm->BindChild(fuchsia::sys2::ChildRef{.name = "isolated-devmgr"}, |
| exposed_dir.NewRequest(), &result)); |
| if (status.is_error() || result.is_err()) { |
| FX_LOGS(ERROR) << "Unable to connect to child: " << status.status_string(); |
| return status; |
| } |
| zx::channel handle, request; |
| status = zx::make_status(zx::channel::create(0, &handle, &request)); |
| if (status.is_error()) { |
| FX_LOGS(ERROR) << "Unable to create channel: " << status.status_string(); |
| return status; |
| } |
| status = zx::make_status( |
| exposed_dir->Open(fuchsia::io::OPEN_FLAG_DIRECTORY | fuchsia::io::OPEN_RIGHT_READABLE, |
| fuchsia::io::MODE_TYPE_DIRECTORY, "dev", |
| fidl::InterfaceRequest<fuchsia::io::Node>(std::move(request)))); |
| if (status.is_error()) { |
| FX_LOGS(ERROR) << "Unable to open dev in child: " << status.status_string(); |
| return status; |
| } |
| status = zx::make_status(fdio_ns_bind(name_space, "/dev", handle.release())); |
| if (status.is_error()) { |
| FX_LOGS(ERROR) << "Failed to bind /dev to namespace: " << status.status_string(); |
| return status; |
| } |
| return zx::ok(); |
| } |
| |
| } // namespace isolated_devmgr |