Storage capabilities

<<../../_v2_banner.md>>

A storage capability is a way for components to receive isolated access to a private storage directory. When a storage capability is declared in a component manifest it must reference a backing directory capability. Each component that then uses this storage capability receives a unique and non-overlapping subdirectory within the backing directory. This prevents component instances from accessing files belonging to other component instances (including their own children).

Directory vs storage capabilities

As an example, if component instance a receives a directory capability from its realm and both uses it and offers it to b, which also uses the directory, both component instances can see and interact with the same directory.

<a's realm>
    |
    a
    |
    b

a.cml:
{
    use: [
        {
            directory: "example_dir",
            rights: ["rw*"],
            path: "/example_dir",
        },
    ],
    offer: [
        {
            directory: "example_dir",
            from: "parent",
            to: [ "#b" ],
        },
    ],
}

b.cml:
{
    use: [
        {
            directory: "example_dir",
            rights: ["rw*"],
            path: "/example_dir",
        },
    ],
}

In this example if component instance a creates a file named hippos inside /example_dir then b will be able to see and read this file.

If the component instances use storage capabilities instead of directory capabilities, then component instance b cannot see and read the hippos file.

<a's realm>
    |
    a
    |
    b

a.cml:
{
    use: [
        {
            storage: "data",
            path: "/example_dir",
        },
    ],
    offer: [
        {
            storage: "data",
            from: "parent",
            to: [ "#b" ],
        },
    ],
}

b.cml:
{
    use: [
        {
            storage: "data",
            path: "/example_dir",
        },
    ],
}

Any files that a creates are not visible to b, and vice versa. Storage capabilities provide unique non-overlapping directories to each component instance that uses them.

Creating storage capabilities

Storage capabilities can be created with a storage declaration in a component manifest. Once storage capabilities have been declared, they can then be offered to other component instances.

A storage declaration must include a reference to a backing directory capability. The component manager will create isolated sub-directories within the backing directory, one for each component instance using the storage capability.

For example, the following manifest describes a new storage capability named tmp backed by the memfs directory capability exposed by the child named memfs. From this storage declaration a storage capability is offered to the child named storage-user.

{
    capabilities: [
        {
            storage: "tmp",
            from: "#memfs",
            backing_dir: "memfs",
        },
    ],
    offer: [
        {
            storage: "tmp",
            from: "self",
            to: [ "#storage-user" ],
        },
    ],
    children: [
        { name: "memfs", url: "fuchsia-pkg://..." },
        { name: "storage-user", url: "fuchsia-pkg://...", },
    ],
}

Storage capability semantics

A directory capability that backs storage capabilities can be used to access the files of any component that uses the resulting storage capabilities. This type of directory capability should be routed carefully to avoid exposing this capability to too many component instances.

When a component instance attempts to access the directory provided to it through a storage capability, the framework binds to and generates sub-directories in the component instance that provides the backing directory capability. Then, the framework provides the component instance access to a unique subdirectory.

The subdirectory to which a component instance is provided access is determined by its location in the component topology. This means that if a component instance is renamed in its parent manifest or moved to a different parent then it will receive a different subdirectory than it did before the change.