Skip to main content

routing_test_helpers/
rights.rs

1// Copyright 2021 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.
4
5use crate::{CheckUse, ExpectedResult, RoutingTestModel, RoutingTestModelBuilder};
6use cm_rust::offer::*;
7use cm_rust::*;
8use cm_rust_testing::*;
9use fidl_fuchsia_io as fio;
10use std::marker::PhantomData;
11use zx_status;
12
13pub struct CommonRightsTest<T: RoutingTestModelBuilder> {
14    builder: PhantomData<T>,
15}
16
17impl<T: RoutingTestModelBuilder> CommonRightsTest<T> {
18    pub fn new() -> Self {
19        Self { builder: PhantomData }
20    }
21
22    pub async fn test_offer_increasing_rights(&self) {
23        let components = vec![
24            (
25                "a",
26                ComponentDeclBuilder::new()
27                    .offer(
28                        OfferBuilder::directory()
29                            .name("bar_data")
30                            .target_name("baz_data")
31                            .source_static_child("b")
32                            .target_static_child("c")
33                            .rights(fio::RW_STAR_DIR),
34                    )
35                    .child_default("b")
36                    .child_default("c")
37                    .build(),
38            ),
39            (
40                "b",
41                ComponentDeclBuilder::new()
42                    .capability(
43                        CapabilityBuilder::directory()
44                            .name("foo_data")
45                            .path("/data/foo")
46                            .rights(fio::RW_STAR_DIR),
47                    )
48                    .expose(
49                        ExposeBuilder::directory()
50                            .name("foo_data")
51                            .source(ExposeSource::Self_)
52                            .target_name("bar_data")
53                            .rights(fio::RW_STAR_DIR),
54                    )
55                    .build(),
56            ),
57            (
58                "c",
59                ComponentDeclBuilder::new()
60                    .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
61                    .build(),
62            ),
63        ];
64        let model = T::new("a", components).build().await;
65        model
66            .check_use(["c"].try_into().unwrap(), CheckUse::default_directory(ExpectedResult::Ok))
67            .await;
68    }
69
70    pub async fn test_offer_incompatible_rights(&self) {
71        let components = vec![
72            (
73                "a",
74                ComponentDeclBuilder::new()
75                    .offer(
76                        OfferBuilder::directory()
77                            .name("bar_data")
78                            .target_name("baz_data")
79                            .source_static_child("b")
80                            .target_static_child("c")
81                            .rights(fio::W_STAR_DIR),
82                    )
83                    .child_default("b")
84                    .child_default("c")
85                    .build(),
86            ),
87            (
88                "b",
89                ComponentDeclBuilder::new()
90                    .capability(
91                        CapabilityBuilder::directory()
92                            .name("foo_data")
93                            .path("/data/foo")
94                            .rights(fio::RW_STAR_DIR),
95                    )
96                    .expose(
97                        ExposeBuilder::directory()
98                            .name("foo_data")
99                            .source(ExposeSource::Self_)
100                            .target_name("bar_data")
101                            .rights(fio::RW_STAR_DIR),
102                    )
103                    .build(),
104            ),
105            (
106                "c",
107                ComponentDeclBuilder::new()
108                    // Default rights on `UseBuilder::directory` are `fio::R_STAR_DIR`
109                    .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
110                    .build(),
111            ),
112        ];
113        let model = T::new("a", components).build().await;
114        model
115            .check_use(
116                ["c"].try_into().unwrap(),
117                CheckUse::default_directory(ExpectedResult::Err(zx_status::Status::ACCESS_DENIED)),
118            )
119            .await;
120    }
121
122    pub async fn test_expose_increasing_rights(&self) {
123        let components = vec![
124            (
125                "a",
126                ComponentDeclBuilder::new()
127                    .offer(
128                        OfferBuilder::directory()
129                            .name("bar_data")
130                            .target_name("baz_data")
131                            .source_static_child("b")
132                            .target_static_child("c")
133                            .rights(fio::R_STAR_DIR),
134                    )
135                    .child_default("b")
136                    .child_default("c")
137                    .build(),
138            ),
139            (
140                "b",
141                ComponentDeclBuilder::new()
142                    .capability(
143                        CapabilityBuilder::directory()
144                            .name("foo_data")
145                            .path("/data/foo")
146                            .rights(fio::RW_STAR_DIR),
147                    )
148                    .expose(
149                        ExposeBuilder::directory()
150                            .name("foo_data")
151                            .source(ExposeSource::Self_)
152                            .target_name("bar_data")
153                            .rights(fio::RW_STAR_DIR),
154                    )
155                    .build(),
156            ),
157            (
158                "c",
159                ComponentDeclBuilder::new()
160                    .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
161                    .build(),
162            ),
163        ];
164        let model = T::new("a", components).build().await;
165        model
166            .check_use(["c"].try_into().unwrap(), CheckUse::default_directory(ExpectedResult::Ok))
167            .await;
168    }
169
170    pub async fn test_expose_incompatible_rights(&self) {
171        let components = vec![
172            (
173                "a",
174                ComponentDeclBuilder::new()
175                    .offer(
176                        OfferBuilder::directory()
177                            .name("bar_data")
178                            .target_name("baz_data")
179                            .source_static_child("b")
180                            .target_static_child("c")
181                            .rights(fio::RW_STAR_DIR),
182                    )
183                    .child_default("b")
184                    .child_default("c")
185                    .build(),
186            ),
187            (
188                "b",
189                ComponentDeclBuilder::new()
190                    .capability(
191                        CapabilityBuilder::directory()
192                            .name("foo_data")
193                            .path("/data/foo")
194                            .rights(fio::RW_STAR_DIR),
195                    )
196                    .expose(
197                        ExposeBuilder::directory()
198                            .name("foo_data")
199                            .source(ExposeSource::Self_)
200                            .target_name("bar_data")
201                            .rights(fio::W_STAR_DIR),
202                    )
203                    .build(),
204            ),
205            (
206                "c",
207                ComponentDeclBuilder::new()
208                    .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
209                    .build(),
210            ),
211        ];
212        let model = T::new("a", components).build().await;
213        model
214            .check_use(
215                ["c"].try_into().unwrap(),
216                CheckUse::default_directory(ExpectedResult::Err(zx_status::Status::ACCESS_DENIED)),
217            )
218            .await;
219    }
220
221    pub async fn test_capability_increasing_rights(&self) {
222        let components = vec![
223            (
224                "a",
225                ComponentDeclBuilder::new()
226                    .offer(
227                        OfferBuilder::directory()
228                            .name("bar_data")
229                            .target_name("baz_data")
230                            .source_static_child("b")
231                            .target_static_child("c")
232                            .rights(fio::R_STAR_DIR),
233                    )
234                    .child_default("b")
235                    .child_default("c")
236                    .build(),
237            ),
238            (
239                "b",
240                ComponentDeclBuilder::new()
241                    .capability(
242                        CapabilityBuilder::directory()
243                            .name("foo_data")
244                            .path("/data/foo")
245                            .rights(fio::RW_STAR_DIR),
246                    )
247                    .expose(
248                        ExposeBuilder::directory()
249                            .name("foo_data")
250                            .source(ExposeSource::Self_)
251                            .target_name("bar_data")
252                            .rights(fio::R_STAR_DIR),
253                    )
254                    .build(),
255            ),
256            (
257                "c",
258                ComponentDeclBuilder::new()
259                    .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
260                    .build(),
261            ),
262        ];
263        let model = T::new("a", components).build().await;
264        model
265            .check_use(["c"].try_into().unwrap(), CheckUse::default_directory(ExpectedResult::Ok))
266            .await;
267    }
268
269    pub async fn test_capability_incompatible_rights(&self) {
270        let components = vec![
271            (
272                "a",
273                ComponentDeclBuilder::new()
274                    .offer(
275                        OfferBuilder::directory()
276                            .name("bar_data")
277                            .target_name("baz_data")
278                            .source_static_child("b")
279                            .target_static_child("c")
280                            .rights(fio::RW_STAR_DIR),
281                    )
282                    .child_default("b")
283                    .child_default("c")
284                    .build(),
285            ),
286            (
287                "b",
288                ComponentDeclBuilder::new()
289                    .capability(
290                        CapabilityBuilder::directory()
291                            .name("foo_data")
292                            .path("/data/foo")
293                            .rights(fio::W_STAR_DIR),
294                    )
295                    .expose(
296                        ExposeBuilder::directory()
297                            .name("foo_data")
298                            .source(ExposeSource::Self_)
299                            .target_name("bar_data")
300                            .rights(fio::RW_STAR_DIR),
301                    )
302                    .build(),
303            ),
304            (
305                "c",
306                ComponentDeclBuilder::new()
307                    .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
308                    .build(),
309            ),
310        ];
311        let model = T::new("a", components).build().await;
312        model
313            .check_use(
314                ["c"].try_into().unwrap(),
315                CheckUse::default_directory(ExpectedResult::Err(zx_status::Status::ACCESS_DENIED)),
316            )
317            .await;
318    }
319
320    ///  component manager's namespace
321    ///   |
322    ///   a
323    ///    \
324    ///     b
325    ///
326    /// a: offers directory /offer_from_cm_namespace/data/foo from realm as bar_data
327    /// b: uses directory bar_data as /data/hippo, but the rights don't match
328    pub async fn test_offer_from_component_manager_namespace_directory_incompatible_rights(&self) {
329        let components = vec![
330            (
331                "a",
332                ComponentDeclBuilder::new()
333                    .offer(
334                        OfferBuilder::directory()
335                            .name("foo_data")
336                            .target_name("bar_data")
337                            .source(OfferSource::Parent)
338                            .target_static_child("b"),
339                    )
340                    .child_default("b")
341                    .build(),
342            ),
343            (
344                "b",
345                ComponentDeclBuilder::new()
346                    .use_(UseBuilder::directory().name("bar_data").path("/data/hippo"))
347                    .build(),
348            ),
349        ];
350        let namespace_capabilities = vec![
351            CapabilityBuilder::directory()
352                .name("foo_data")
353                .path("/offer_from_cm_namespace/data/foo")
354                .rights(fio::W_STAR_DIR)
355                .build(),
356        ];
357        let mut builder = T::new("a", components);
358        builder.set_namespace_capabilities(namespace_capabilities);
359        let model = builder.build().await;
360
361        model.install_namespace_directory("/offer_from_cm_namespace");
362        model
363            .check_use(
364                ["b"].try_into().unwrap(),
365                CheckUse::default_directory(ExpectedResult::Err(zx_status::Status::ACCESS_DENIED)),
366            )
367            .await;
368    }
369}