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