From 44d71fea92d0dbf197eae13d7d4939be43af47a2 Mon Sep 17 00:00:00 2001
From: Abdulla Kamar <abdulla@google.com>
Date: Sun, 12 May 2019 22:04:10 +0000
Subject: [PATCH] [bootsvc] Add fuchsia.boot.RootJob service

This allows processes further down the job-hierarchy to be able to get
access to the RootJob. This is useful for processes such as the
devcoordinator (once component_manager is in place) and utilities like
ps.

Eventually, we will want to further limit or entirely get rid of this
interface. That will happen once component_manager is in place.

ZX-4002
ZX-4072

Change-Id: I4b1e75a7841a04ea2cc7da374e42257d4802e619
---
 zircon/system/core/bootsvc/TESTING            |  6 ++---
 .../system/core/bootsvc/integration-test.cpp  | 23 +++++++++++++++++++
 zircon/system/core/bootsvc/main.cpp           |  2 ++
 zircon/system/core/bootsvc/svcfs-service.cpp  | 22 ++++++++++++++++++
 zircon/system/core/bootsvc/svcfs-service.h    |  3 +++
 zircon/system/fidl/fuchsia-boot/BUILD.gn      |  1 +
 zircon/system/fidl/fuchsia-boot/root-job.fidl | 14 +++++++++++
 7 files changed, 68 insertions(+), 3 deletions(-)
 create mode 100644 zircon/system/fidl/fuchsia-boot/root-job.fidl

diff --git a/zircon/system/core/bootsvc/TESTING b/zircon/system/core/bootsvc/TESTING
index 9344253d64a..0db49573d16 100644
--- a/zircon/system/core/bootsvc/TESTING
+++ b/zircon/system/core/bootsvc/TESTING
@@ -10,8 +10,8 @@ To test that crashlogs are being added to bootfs, you need to add a CRASHLOG ite
 to the boot zbi.  For example, to add the contents of README.md as the crashlog:
 ```
 $ scripts/build-zircon-x64 &&
-  build-x64/tools/zbi -o build-x64/zircon.zbi build-x64/zircon.zbi \
+  build-gcc/tools/zbi -o build-gcc/zircon.zbi build-gcc/zircon.zbi \
     -T CRASHLOG README.md &&
-  scripts/run-zircon-x64  -V -k  -q $(pwd)/../buildtools/linux-x64/qemu/bin \
-    -c userboot=bin/bootsvc -c bootsvc.next=bin/bootsvc-tests
+  scripts/run-zircon-x64 -k -c userboot=bin/bootsvc \
+    -c bootsvc.next=bin/bootsvc-integration-test,testargument
 ```
diff --git a/zircon/system/core/bootsvc/integration-test.cpp b/zircon/system/core/bootsvc/integration-test.cpp
index 4a416039959..eadfacf6c12 100644
--- a/zircon/system/core/bootsvc/integration-test.cpp
+++ b/zircon/system/core/bootsvc/integration-test.cpp
@@ -42,6 +42,7 @@ namespace {
 
 constexpr char kArgumentsPath[] = "/bootsvc/" fuchsia_boot_Arguments_Name;
 constexpr char kItemsPath[] = "/bootsvc/" fuchsia_boot_Items_Name;
+constexpr char kRootJobPath[] = "/bootsvc/" fuchsia_boot_RootJob_Name;
 constexpr char kRootResourcePath[] = "/bootsvc/" fuchsia_boot_RootResource_Name;
 
 // Make sure the loader works
@@ -166,6 +167,27 @@ bool TestBootItems() {
     END_TEST;
 }
 
+// Make sure the fuchsia.boot.RootJob service works
+bool TestBootRootJob() {
+    BEGIN_TEST;
+
+    zx::channel local, remote;
+    zx_status_t status = zx::channel::create(0, &local, &remote);
+    ASSERT_EQ(ZX_OK, status);
+
+    // Check that we can open the fuchsia.boot.RootJob service.
+    status = fdio_service_connect(kRootJobPath, remote.release());
+    ASSERT_EQ(ZX_OK, status);
+
+    // Check that we received a job from the service.
+    zx::job root_job;
+    status = fuchsia_boot_RootJobGet(local.get(), root_job.reset_and_get_address());
+    ASSERT_EQ(ZX_OK, status);
+    ASSERT_TRUE(root_job.is_valid());
+
+    END_TEST;
+}
+
 // Make sure the fuchsia.boot.RootResource service works
 bool TestBootRootResource() {
     BEGIN_TEST;
@@ -222,6 +244,7 @@ RUN_TEST(TestNamespace)
 RUN_TEST(TestArguments)
 RUN_TEST(TestBootArguments)
 RUN_TEST(TestBootItems)
+RUN_TEST(TestBootRootJob)
 RUN_TEST(TestBootRootResource)
 RUN_TEST(TestVdsosPresent)
 END_TEST_CASE(bootsvc_integration_tests)
diff --git a/zircon/system/core/bootsvc/main.cpp b/zircon/system/core/bootsvc/main.cpp
index e681897ebfe..cd3d61bb58c 100644
--- a/zircon/system/core/bootsvc/main.cpp
+++ b/zircon/system/core/bootsvc/main.cpp
@@ -246,6 +246,8 @@ int main(int argc, char** argv) {
     svcfs_svc->AddService(fuchsia_boot_Items_Name,
                           bootsvc::CreateItemsService(loop.dispatcher(), std::move(image_vmo),
                                                       std::move(item_map)));
+    svcfs_svc->AddService(fuchsia_boot_RootJob_Name,
+                          bootsvc::CreateRootJobService(loop.dispatcher()));
     svcfs_svc->AddService(fuchsia_boot_RootResource_Name,
                           bootsvc::CreateRootResourceService(loop.dispatcher()));
 
diff --git a/zircon/system/core/bootsvc/svcfs-service.cpp b/zircon/system/core/bootsvc/svcfs-service.cpp
index e2ba5b4efc4..a92abc58ac7 100644
--- a/zircon/system/core/bootsvc/svcfs-service.cpp
+++ b/zircon/system/core/bootsvc/svcfs-service.cpp
@@ -6,6 +6,7 @@
 
 #include <fuchsia/boot/c/fidl.h>
 #include <lib/fidl-async/bind.h>
+#include <lib/zx/job.h>
 #include <zircon/process.h>
 #include <zircon/processargs.h>
 #include <zircon/status.h>
@@ -80,6 +81,20 @@ zx_status_t RootResourceGet(void* ctx, fidl_txn_t* txn) {
     return fuchsia_boot_RootResourceGet_reply(txn, resource.release());
 }
 
+zx_status_t RootJobGet(void* ctx, fidl_txn_t* txn) {
+    zx::job dup;
+    zx_status_t status = zx::job::default_job()->duplicate(ZX_RIGHT_SAME_RIGHTS, &dup);
+    if (status != ZX_OK) {
+        printf("bootsvc: Failed to duplicate root job: %s\n", zx_status_get_string(status));
+        return status;
+    }
+    return fuchsia_boot_RootJobGet_reply(txn, dup.release());
+}
+
+constexpr fuchsia_boot_RootJob_ops kRootJobOps = {
+    .Get = RootJobGet,
+};
+
 constexpr fuchsia_boot_RootResource_ops kRootResourceOps = {
     .Get = RootResourceGet,
 };
@@ -123,6 +138,13 @@ fbl::RefPtr<fs::Service> CreateItemsService(async_dispatcher_t* dispatcher, zx::
         });
 }
 
+fbl::RefPtr<fs::Service> CreateRootJobService(async_dispatcher_t* dispatcher) {
+    return fbl::MakeRefCounted<fs::Service>([dispatcher](zx::channel channel) {
+        auto dispatch = reinterpret_cast<fidl_dispatch_t*>(fuchsia_boot_RootJob_dispatch);
+        return fidl_bind(dispatcher, channel.release(), dispatch, nullptr, &kRootJobOps);
+    });
+}
+
 fbl::RefPtr<fs::Service> CreateRootResourceService(async_dispatcher_t* dispatcher) {
     return fbl::MakeRefCounted<fs::Service>([dispatcher](zx::channel channel) {
         auto dispatch = reinterpret_cast<fidl_dispatch_t*>(fuchsia_boot_RootResource_dispatch);
diff --git a/zircon/system/core/bootsvc/svcfs-service.h b/zircon/system/core/bootsvc/svcfs-service.h
index 4fd8b647482..acbd3e1a8c7 100644
--- a/zircon/system/core/bootsvc/svcfs-service.h
+++ b/zircon/system/core/bootsvc/svcfs-service.h
@@ -49,6 +49,9 @@ fbl::RefPtr<fs::Service> CreateArgumentsService(async_dispatcher_t* dispatcher,
 fbl::RefPtr<fs::Service> CreateItemsService(async_dispatcher_t* dispatcher, zx::vmo vmo,
                                             ItemMap map);
 
+// Create a service to provide the root job.
+fbl::RefPtr<fs::Service> CreateRootJobService(async_dispatcher_t* dispatcher);
+
 // Create a service to provide the root resource.
 fbl::RefPtr<fs::Service> CreateRootResourceService(async_dispatcher_t* dispatcher);
 
diff --git a/zircon/system/fidl/fuchsia-boot/BUILD.gn b/zircon/system/fidl/fuchsia-boot/BUILD.gn
index 27bd70b254f..7d8786684c9 100644
--- a/zircon/system/fidl/fuchsia-boot/BUILD.gn
+++ b/zircon/system/fidl/fuchsia-boot/BUILD.gn
@@ -8,6 +8,7 @@ fidl_library("fuchsia-boot") {
   sources = [
     "arguments.fidl",
     "items.fidl",
+    "root-job.fidl",
     "root-resource.fidl",
   ]
 }
diff --git a/zircon/system/fidl/fuchsia-boot/root-job.fidl b/zircon/system/fidl/fuchsia-boot/root-job.fidl
new file mode 100644
index 00000000000..4fe5d1c22fe
--- /dev/null
+++ b/zircon/system/fidl/fuchsia-boot/root-job.fidl
@@ -0,0 +1,14 @@
+// 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.
+
+library fuchsia.boot;
+
+/// Protocol for providing the root job.
+///
+/// TODO(ZX-4072): Do not use this without first consulting the Zircon team.
+[Discoverable, Layout = "Simple"]
+protocol RootJob {
+    /// Get the root |job|.
+    Get() -> (handle<job> job);
+};
-- 
GitLab