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                    .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
109                    .build(),
110            ),
111        ];
112        let model = T::new("a", components).build().await;
113        model
114            .check_use(
115                ["c"].try_into().unwrap(),
116                CheckUse::default_directory(ExpectedResult::Err(zx_status::Status::ACCESS_DENIED)),
117            )
118            .await;
119    }
120
121    pub async fn test_expose_increasing_rights(&self) {
122        let components = vec![
123            (
124                "a",
125                ComponentDeclBuilder::new()
126                    .offer(
127                        OfferBuilder::directory()
128                            .name("bar_data")
129                            .target_name("baz_data")
130                            .source_static_child("b")
131                            .target_static_child("c")
132                            .rights(fio::R_STAR_DIR),
133                    )
134                    .child_default("b")
135                    .child_default("c")
136                    .build(),
137            ),
138            (
139                "b",
140                ComponentDeclBuilder::new()
141                    .capability(
142                        CapabilityBuilder::directory()
143                            .name("foo_data")
144                            .path("/data/foo")
145                            .rights(fio::RW_STAR_DIR),
146                    )
147                    .expose(
148                        ExposeBuilder::directory()
149                            .name("foo_data")
150                            .source(ExposeSource::Self_)
151                            .target_name("bar_data")
152                            .rights(fio::RW_STAR_DIR),
153                    )
154                    .build(),
155            ),
156            (
157                "c",
158                ComponentDeclBuilder::new()
159                    .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
160                    .build(),
161            ),
162        ];
163        let model = T::new("a", components).build().await;
164        model
165            .check_use(["c"].try_into().unwrap(), CheckUse::default_directory(ExpectedResult::Ok))
166            .await;
167    }
168
169    pub async fn test_expose_incompatible_rights(&self) {
170        let components = vec![
171            (
172                "a",
173                ComponentDeclBuilder::new()
174                    .offer(
175                        OfferBuilder::directory()
176                            .name("bar_data")
177                            .target_name("baz_data")
178                            .source_static_child("b")
179                            .target_static_child("c")
180                            .rights(fio::RW_STAR_DIR),
181                    )
182                    .child_default("b")
183                    .child_default("c")
184                    .build(),
185            ),
186            (
187                "b",
188                ComponentDeclBuilder::new()
189                    .capability(
190                        CapabilityBuilder::directory()
191                            .name("foo_data")
192                            .path("/data/foo")
193                            .rights(fio::RW_STAR_DIR),
194                    )
195                    .expose(
196                        ExposeBuilder::directory()
197                            .name("foo_data")
198                            .source(ExposeSource::Self_)
199                            .target_name("bar_data")
200                            .rights(fio::W_STAR_DIR),
201                    )
202                    .build(),
203            ),
204            (
205                "c",
206                ComponentDeclBuilder::new()
207                    .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
208                    .build(),
209            ),
210        ];
211        let model = T::new("a", components).build().await;
212        model
213            .check_use(
214                ["c"].try_into().unwrap(),
215                CheckUse::default_directory(ExpectedResult::Err(zx_status::Status::ACCESS_DENIED)),
216            )
217            .await;
218    }
219
220    pub async fn test_capability_increasing_rights(&self) {
221        let components = vec![
222            (
223                "a",
224                ComponentDeclBuilder::new()
225                    .offer(
226                        OfferBuilder::directory()
227                            .name("bar_data")
228                            .target_name("baz_data")
229                            .source_static_child("b")
230                            .target_static_child("c")
231                            .rights(fio::R_STAR_DIR),
232                    )
233                    .child_default("b")
234                    .child_default("c")
235                    .build(),
236            ),
237            (
238                "b",
239                ComponentDeclBuilder::new()
240                    .capability(
241                        CapabilityBuilder::directory()
242                            .name("foo_data")
243                            .path("/data/foo")
244                            .rights(fio::RW_STAR_DIR),
245                    )
246                    .expose(
247                        ExposeBuilder::directory()
248                            .name("foo_data")
249                            .source(ExposeSource::Self_)
250                            .target_name("bar_data")
251                            .rights(fio::R_STAR_DIR),
252                    )
253                    .build(),
254            ),
255            (
256                "c",
257                ComponentDeclBuilder::new()
258                    .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
259                    .build(),
260            ),
261        ];
262        let model = T::new("a", components).build().await;
263        model
264            .check_use(["c"].try_into().unwrap(), CheckUse::default_directory(ExpectedResult::Ok))
265            .await;
266    }
267
268    pub async fn test_capability_incompatible_rights(&self) {
269        let components = vec![
270            (
271                "a",
272                ComponentDeclBuilder::new()
273                    .offer(
274                        OfferBuilder::directory()
275                            .name("bar_data")
276                            .target_name("baz_data")
277                            .source_static_child("b")
278                            .target_static_child("c")
279                            .rights(fio::RW_STAR_DIR),
280                    )
281                    .child_default("b")
282                    .child_default("c")
283                    .build(),
284            ),
285            (
286                "b",
287                ComponentDeclBuilder::new()
288                    .capability(
289                        CapabilityBuilder::directory()
290                            .name("foo_data")
291                            .path("/data/foo")
292                            .rights(fio::W_STAR_DIR),
293                    )
294                    .expose(
295                        ExposeBuilder::directory()
296                            .name("foo_data")
297                            .source(ExposeSource::Self_)
298                            .target_name("bar_data")
299                            .rights(fio::RW_STAR_DIR),
300                    )
301                    .build(),
302            ),
303            (
304                "c",
305                ComponentDeclBuilder::new()
306                    .use_(UseBuilder::directory().name("baz_data").path("/data/hippo"))
307                    .build(),
308            ),
309        ];
310        let model = T::new("a", components).build().await;
311        model
312            .check_use(
313                ["c"].try_into().unwrap(),
314                CheckUse::default_directory(ExpectedResult::Err(zx_status::Status::ACCESS_DENIED)),
315            )
316            .await;
317    }
318
319    ///  component manager's namespace
320    ///   |
321    ///   a
322    ///    \
323    ///     b
324    ///
325    /// a: offers directory /offer_from_cm_namespace/data/foo from realm as bar_data
326    /// b: uses directory bar_data as /data/hippo, but the rights don't match
327    pub async fn test_offer_from_component_manager_namespace_directory_incompatible_rights(&self) {
328        let components = vec![
329            (
330                "a",
331                ComponentDeclBuilder::new()
332                    .offer(
333                        OfferBuilder::directory()
334                            .name("foo_data")
335                            .target_name("bar_data")
336                            .source(OfferSource::Parent)
337                            .target_static_child("b"),
338                    )
339                    .child_default("b")
340                    .build(),
341            ),
342            (
343                "b",
344                ComponentDeclBuilder::new()
345                    .use_(UseBuilder::directory().name("bar_data").path("/data/hippo"))
346                    .build(),
347            ),
348        ];
349        let namespace_capabilities = vec![
350            CapabilityBuilder::directory()
351                .name("foo_data")
352                .path("/offer_from_cm_namespace/data/foo")
353                .rights(fio::W_STAR_DIR)
354                .build(),
355        ];
356        let mut builder = T::new("a", components);
357        builder.set_namespace_capabilities(namespace_capabilities);
358        let model = builder.build().await;
359
360        model.install_namespace_directory("/offer_from_cm_namespace");
361        model
362            .check_use(
363                ["b"].try_into().unwrap(),
364                CheckUse::default_directory(ExpectedResult::Err(zx_status::Status::ACCESS_DENIED)),
365            )
366            .await;
367    }
368}