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}