serve_processargs/lib.rs
1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4use fuchsia_runtime::{HandleInfo, HandleType};
5use sandbox::{Capability, DictKey};
6use std::collections::HashMap;
7use thiserror::Error;
8
9mod namespace;
10
11pub use crate::namespace::{ignore_not_found, BuildNamespaceError, NamespaceBuilder};
12
13/// How to deliver a particular capability from a dict to an Elf process. Broadly speaking,
14/// one could either deliver a capability using namespace entries, or using numbered handles.
15pub enum Delivery {
16 /// Install the capability as a `fuchsia.io` object, within some parent directory serviced by
17 /// the framework, and discoverable at a path such as "/svc/foo/bar".
18 ///
19 /// As a result, a namespace entry will be created in the resulting processargs, corresponding
20 /// to the parent directory, e.g. "/svc/foo".
21 ///
22 /// For example, installing a `sandbox::Sender` at "/svc/fuchsia.examples.Echo" will
23 /// cause the framework to spin up a `fuchsia.io/Directory` implementation backing "/svc",
24 /// containing a filesystem object named "fuchsia.examples.Echo".
25 ///
26 /// Not all capability types are installable as `fuchsia.io` objects. A one-shot handle is not
27 /// supported because `fuchsia.io` does not have a protocol for delivering one-shot handles.
28 /// Use [Delivery::Handle] for those.
29 NamespacedObject(cm_types::Path),
30
31 /// Install the capability as a `fuchsia.io` object by creating a namespace entry at the
32 /// provided path. The difference between [Delivery::NamespacedObject] and
33 /// [Delivery::NamespaceEntry] is that the former will create a namespace entry at the parent
34 /// directory.
35 ///
36 /// For example, installing a `sandbox::Directory` at "/data" will result in a namespace entry
37 /// at "/data". A request will be sent to the capability when the user writes to the
38 /// namespace entry.
39 NamespaceEntry(cm_types::Path),
40
41 /// Installs the Zircon handle representation of this capability at the processargs slot
42 /// described by [HandleInfo].
43 ///
44 /// The following handle types are disallowed because they will collide with the implementation
45 /// of incoming namespace and outgoing directory:
46 ///
47 /// - [HandleType::NamespaceDirectory]
48 /// - [HandleType::DirectoryRequest]
49 ///
50 Handle(HandleInfo),
51}
52
53pub enum DeliveryMapEntry {
54 Delivery(Delivery),
55 Dict(DeliveryMap),
56}
57
58/// A nested dictionary mapping capability names to delivery method.
59///
60/// Each entry in a [Dict] should have a corresponding entry here describing how the
61/// capability will be delivered to the process. If a [Dict] has a nested [Dict], then there
62/// will be a corresponding nested [DeliveryMapEntry::Dict] containing the [DeliveryMap] for the
63/// capabilities in the nested [Dict].
64pub type DeliveryMap = HashMap<DictKey, DeliveryMapEntry>;
65
66#[derive(Error, Debug)]
67pub enum DeliveryError {
68 #[error("the key `{0}` is not found in the dict")]
69 NotInDict(DictKey),
70
71 #[error("wrong type: the delivery map expected `{0}` to be a nested Dict in the dict")]
72 NotADict(DictKey),
73
74 #[error("unused capabilities in dict: `{0:?}`")]
75 UnusedCapabilities(Vec<DictKey>),
76
77 #[error("handle type `{0:?}` is not allowed to be installed into processargs")]
78 UnsupportedHandleType(HandleType),
79
80 #[error("namespace configuration error: `{0}`")]
81 NamespaceError(namespace::BuildNamespaceError),
82
83 #[error("capability `{0:?}` is not allowed to be installed into processargs")]
84 UnsupportedCapability(Capability),
85}