blob: f555c12c843060f5bad465f0736d56bef0374dab [file] [log] [blame]
David Drysdale2566fb32024-07-09 14:46:37 +01001// Copyright 2020, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Access control tests.
16
17use super::*;
18use crate::key_perm_set;
19use anyhow::anyhow;
20use anyhow::Result;
21use keystore2_selinux::*;
22
23const ALL_PERMS: KeyPermSet = key_perm_set![
24 KeyPerm::ManageBlob,
25 KeyPerm::Delete,
26 KeyPerm::UseDevId,
27 KeyPerm::ReqForcedOp,
28 KeyPerm::GenUniqueId,
29 KeyPerm::Grant,
30 KeyPerm::GetInfo,
31 KeyPerm::Rebind,
32 KeyPerm::Update,
33 KeyPerm::Use,
34 KeyPerm::ConvertStorageKeyToEphemeral,
35];
36
37const SYSTEM_SERVER_PERMISSIONS_NO_GRANT: KeyPermSet = key_perm_set![
38 KeyPerm::Delete,
39 KeyPerm::UseDevId,
40 // No KeyPerm::Grant
41 KeyPerm::GetInfo,
42 KeyPerm::Rebind,
43 KeyPerm::Update,
44 KeyPerm::Use,
45];
46
47const NOT_GRANT_PERMS: KeyPermSet = key_perm_set![
48 KeyPerm::ManageBlob,
49 KeyPerm::Delete,
50 KeyPerm::UseDevId,
51 KeyPerm::ReqForcedOp,
52 KeyPerm::GenUniqueId,
53 // No KeyPerm::Grant
54 KeyPerm::GetInfo,
55 KeyPerm::Rebind,
56 KeyPerm::Update,
57 KeyPerm::Use,
58 KeyPerm::ConvertStorageKeyToEphemeral,
59];
60
61const UNPRIV_PERMS: KeyPermSet = key_perm_set![
62 KeyPerm::Delete,
63 KeyPerm::GetInfo,
64 KeyPerm::Rebind,
65 KeyPerm::Update,
66 KeyPerm::Use,
67];
68
69/// The su_key namespace as defined in su.te and keystore_key_contexts of the
70/// SePolicy (system/sepolicy).
71const SU_KEY_NAMESPACE: i32 = 0;
72/// The shell_key namespace as defined in shell.te and keystore_key_contexts of the
73/// SePolicy (system/sepolicy).
74const SHELL_KEY_NAMESPACE: i32 = 1;
75
76pub fn test_getcon() -> Result<Context> {
77 Context::new("u:object_r:keystore:s0")
78}
79
80// This macro evaluates the given expression and checks that
81// a) evaluated to Result::Err() and that
82// b) the wrapped error is selinux::Error::perm() (permission denied).
83// We use a macro here because a function would mask which invocation caused the failure.
84//
85// TODO b/164121720 Replace this macro with a function when `track_caller` is available.
86macro_rules! assert_perm_failed {
87 ($test_function:expr) => {
88 let result = $test_function;
89 assert!(result.is_err(), "Permission check should have failed.");
90 assert_eq!(
91 Some(&selinux::Error::perm()),
92 result.err().unwrap().root_cause().downcast_ref::<selinux::Error>()
93 );
94 };
95}
96
97fn check_context() -> Result<(selinux::Context, i32, bool)> {
98 // Calling the non mocked selinux::getcon here intended.
99 let context = selinux::getcon()?;
100 match context.to_str().unwrap() {
101 "u:r:su:s0" => Ok((context, SU_KEY_NAMESPACE, true)),
102 "u:r:shell:s0" => Ok((context, SHELL_KEY_NAMESPACE, false)),
103 c => Err(anyhow!(format!(
104 "This test must be run as \"su\" or \"shell\". Current context: \"{}\"",
105 c
106 ))),
107 }
108}
109
110#[test]
111fn check_keystore_permission_test() -> Result<()> {
112 let system_server_ctx = Context::new("u:r:system_server:s0")?;
113 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::AddAuth).is_ok());
114 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ClearNs).is_ok());
115 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::Lock).is_ok());
116 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::Reset).is_ok());
117 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::Unlock).is_ok());
118 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ChangeUser).is_ok());
119 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ChangePassword).is_ok());
120 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ClearUID).is_ok());
121 let shell_ctx = Context::new("u:r:shell:s0")?;
122 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::AddAuth));
123 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ClearNs));
124 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::List));
125 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::Lock));
126 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::Reset));
127 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::Unlock));
128 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ChangeUser));
129 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ChangePassword));
130 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ClearUID));
131 Ok(())
132}
133
134#[test]
135fn check_grant_permission_app() -> Result<()> {
136 let system_server_ctx = Context::new("u:r:system_server:s0")?;
137 let shell_ctx = Context::new("u:r:shell:s0")?;
138 let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
139 check_grant_permission(&system_server_ctx, SYSTEM_SERVER_PERMISSIONS_NO_GRANT, &key)
140 .expect("Grant permission check failed.");
141
142 // attempts to grant the grant permission must always fail even when privileged.
143 assert_perm_failed!(check_grant_permission(&system_server_ctx, KeyPerm::Grant.into(), &key));
144 // unprivileged grant attempts always fail. shell does not have the grant permission.
145 assert_perm_failed!(check_grant_permission(&shell_ctx, UNPRIV_PERMS, &key));
146 Ok(())
147}
148
149#[test]
150fn check_grant_permission_selinux() -> Result<()> {
151 let (sctx, namespace, is_su) = check_context()?;
152 let key = KeyDescriptor {
153 domain: Domain::SELINUX,
154 nspace: namespace as i64,
155 alias: None,
156 blob: None,
157 };
158 if is_su {
159 assert!(check_grant_permission(&sctx, NOT_GRANT_PERMS, &key).is_ok());
160 // attempts to grant the grant permission must always fail even when privileged.
161 assert_perm_failed!(check_grant_permission(&sctx, KeyPerm::Grant.into(), &key));
162 } else {
163 // unprivileged grant attempts always fail. shell does not have the grant permission.
164 assert_perm_failed!(check_grant_permission(&sctx, UNPRIV_PERMS, &key));
165 }
166 Ok(())
167}
168
169#[test]
170fn check_key_permission_domain_grant() -> Result<()> {
171 let key = KeyDescriptor { domain: Domain::GRANT, nspace: 0, alias: None, blob: None };
172
173 assert_perm_failed!(check_key_permission(
174 0,
175 &selinux::Context::new("ignored").unwrap(),
176 KeyPerm::Grant,
177 &key,
178 &Some(UNPRIV_PERMS)
179 ));
180
181 check_key_permission(
182 0,
183 &selinux::Context::new("ignored").unwrap(),
184 KeyPerm::Use,
185 &key,
186 &Some(ALL_PERMS),
187 )
188}
189
190#[test]
191fn check_key_permission_domain_app() -> Result<()> {
192 let system_server_ctx = Context::new("u:r:system_server:s0")?;
193 let shell_ctx = Context::new("u:r:shell:s0")?;
194 let gmscore_app = Context::new("u:r:gmscore_app:s0")?;
195
196 let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
197
198 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Use, &key, &None).is_ok());
199 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Delete, &key, &None).is_ok());
200 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::GetInfo, &key, &None).is_ok());
201 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Rebind, &key, &None).is_ok());
202 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Update, &key, &None).is_ok());
203 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Grant, &key, &None).is_ok());
204 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::UseDevId, &key, &None).is_ok());
205 assert!(check_key_permission(0, &gmscore_app, KeyPerm::GenUniqueId, &key, &None).is_ok());
206
207 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Use, &key, &None).is_ok());
208 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Delete, &key, &None).is_ok());
209 assert!(check_key_permission(0, &shell_ctx, KeyPerm::GetInfo, &key, &None).is_ok());
210 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Rebind, &key, &None).is_ok());
211 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Update, &key, &None).is_ok());
212 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::Grant, &key, &None));
213 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::ReqForcedOp, &key, &None));
214 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::ManageBlob, &key, &None));
215 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::UseDevId, &key, &None));
216 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::GenUniqueId, &key, &None));
217
218 // Also make sure that the permission fails if the caller is not the owner.
219 assert_perm_failed!(check_key_permission(
220 1, // the owner is 0
221 &system_server_ctx,
222 KeyPerm::Use,
223 &key,
224 &None
225 ));
226 // Unless there was a grant.
227 assert!(check_key_permission(
228 1,
229 &system_server_ctx,
230 KeyPerm::Use,
231 &key,
232 &Some(key_perm_set![KeyPerm::Use])
233 )
234 .is_ok());
235 // But fail if the grant did not cover the requested permission.
236 assert_perm_failed!(check_key_permission(
237 1,
238 &system_server_ctx,
239 KeyPerm::Use,
240 &key,
241 &Some(key_perm_set![KeyPerm::GetInfo])
242 ));
243
244 Ok(())
245}
246
247#[test]
248fn check_key_permission_domain_selinux() -> Result<()> {
249 let (sctx, namespace, is_su) = check_context()?;
250 let key = KeyDescriptor {
251 domain: Domain::SELINUX,
252 nspace: namespace as i64,
253 alias: None,
254 blob: None,
255 };
256
257 assert!(check_key_permission(0, &sctx, KeyPerm::Use, &key, &None).is_ok());
258 assert!(check_key_permission(0, &sctx, KeyPerm::Delete, &key, &None).is_ok());
259 assert!(check_key_permission(0, &sctx, KeyPerm::GetInfo, &key, &None).is_ok());
260 assert!(check_key_permission(0, &sctx, KeyPerm::Rebind, &key, &None).is_ok());
261 assert!(check_key_permission(0, &sctx, KeyPerm::Update, &key, &None).is_ok());
262
263 if is_su {
264 assert!(check_key_permission(0, &sctx, KeyPerm::Grant, &key, &None).is_ok());
265 assert!(check_key_permission(0, &sctx, KeyPerm::ManageBlob, &key, &None).is_ok());
266 assert!(check_key_permission(0, &sctx, KeyPerm::UseDevId, &key, &None).is_ok());
267 assert!(check_key_permission(0, &sctx, KeyPerm::GenUniqueId, &key, &None).is_ok());
268 assert!(check_key_permission(0, &sctx, KeyPerm::ReqForcedOp, &key, &None).is_ok());
269 } else {
270 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::Grant, &key, &None));
271 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::ReqForcedOp, &key, &None));
272 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::ManageBlob, &key, &None));
273 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::UseDevId, &key, &None));
274 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::GenUniqueId, &key, &None));
275 }
276 Ok(())
277}
278
279#[test]
280fn check_key_permission_domain_blob() -> Result<()> {
281 let (sctx, namespace, is_su) = check_context()?;
282 let key =
283 KeyDescriptor { domain: Domain::BLOB, nspace: namespace as i64, alias: None, blob: None };
284
285 if is_su {
286 check_key_permission(0, &sctx, KeyPerm::Use, &key, &None)
287 } else {
288 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::Use, &key, &None));
289 Ok(())
290 }
291}
292
293#[test]
294fn check_key_permission_domain_key_id() -> Result<()> {
295 let key = KeyDescriptor { domain: Domain::KEY_ID, nspace: 0, alias: None, blob: None };
296
297 assert_eq!(
298 Some(&KsError::sys()),
299 check_key_permission(
300 0,
301 &selinux::Context::new("ignored").unwrap(),
302 KeyPerm::Use,
303 &key,
304 &None
305 )
306 .err()
307 .unwrap()
308 .root_cause()
309 .downcast_ref::<KsError>()
310 );
311 Ok(())
312}
313
314#[test]
315fn key_perm_set_all_test() {
316 let v = key_perm_set![
317 KeyPerm::ManageBlob,
318 KeyPerm::Delete,
319 KeyPerm::UseDevId,
320 KeyPerm::ReqForcedOp,
321 KeyPerm::GenUniqueId,
322 KeyPerm::Grant,
323 KeyPerm::GetInfo,
324 KeyPerm::Rebind,
325 KeyPerm::Update,
326 KeyPerm::Use // Test if the macro accepts missing comma at the end of the list.
327 ];
328 let mut i = v.into_iter();
329 assert_eq!(i.next().unwrap().name(), "delete");
330 assert_eq!(i.next().unwrap().name(), "gen_unique_id");
331 assert_eq!(i.next().unwrap().name(), "get_info");
332 assert_eq!(i.next().unwrap().name(), "grant");
333 assert_eq!(i.next().unwrap().name(), "manage_blob");
334 assert_eq!(i.next().unwrap().name(), "rebind");
335 assert_eq!(i.next().unwrap().name(), "req_forced_op");
336 assert_eq!(i.next().unwrap().name(), "update");
337 assert_eq!(i.next().unwrap().name(), "use");
338 assert_eq!(i.next().unwrap().name(), "use_dev_id");
339 assert_eq!(None, i.next());
340}
341#[test]
342fn key_perm_set_sparse_test() {
343 let v = key_perm_set![
344 KeyPerm::ManageBlob,
345 KeyPerm::ReqForcedOp,
346 KeyPerm::GenUniqueId,
347 KeyPerm::Update,
348 KeyPerm::Use, // Test if macro accepts the comma at the end of the list.
349 ];
350 let mut i = v.into_iter();
351 assert_eq!(i.next().unwrap().name(), "gen_unique_id");
352 assert_eq!(i.next().unwrap().name(), "manage_blob");
353 assert_eq!(i.next().unwrap().name(), "req_forced_op");
354 assert_eq!(i.next().unwrap().name(), "update");
355 assert_eq!(i.next().unwrap().name(), "use");
356 assert_eq!(None, i.next());
357}
358#[test]
359fn key_perm_set_empty_test() {
360 let v = key_perm_set![];
361 let mut i = v.into_iter();
362 assert_eq!(None, i.next());
363}
364#[test]
365fn key_perm_set_include_subset_test() {
366 let v1 = key_perm_set![
367 KeyPerm::ManageBlob,
368 KeyPerm::Delete,
369 KeyPerm::UseDevId,
370 KeyPerm::ReqForcedOp,
371 KeyPerm::GenUniqueId,
372 KeyPerm::Grant,
373 KeyPerm::GetInfo,
374 KeyPerm::Rebind,
375 KeyPerm::Update,
376 KeyPerm::Use,
377 ];
378 let v2 = key_perm_set![
379 KeyPerm::ManageBlob,
380 KeyPerm::Delete,
381 KeyPerm::Rebind,
382 KeyPerm::Update,
383 KeyPerm::Use,
384 ];
385 assert!(v1.includes(v2));
386 assert!(!v2.includes(v1));
387}
388#[test]
389fn key_perm_set_include_equal_test() {
390 let v1 = key_perm_set![
391 KeyPerm::ManageBlob,
392 KeyPerm::Delete,
393 KeyPerm::Rebind,
394 KeyPerm::Update,
395 KeyPerm::Use,
396 ];
397 let v2 = key_perm_set![
398 KeyPerm::ManageBlob,
399 KeyPerm::Delete,
400 KeyPerm::Rebind,
401 KeyPerm::Update,
402 KeyPerm::Use,
403 ];
404 assert!(v1.includes(v2));
405 assert!(v2.includes(v1));
406}
407#[test]
408fn key_perm_set_include_overlap_test() {
409 let v1 = key_perm_set![
410 KeyPerm::ManageBlob,
411 KeyPerm::Delete,
412 KeyPerm::Grant, // only in v1
413 KeyPerm::Rebind,
414 KeyPerm::Update,
415 KeyPerm::Use,
416 ];
417 let v2 = key_perm_set![
418 KeyPerm::ManageBlob,
419 KeyPerm::Delete,
420 KeyPerm::ReqForcedOp, // only in v2
421 KeyPerm::Rebind,
422 KeyPerm::Update,
423 KeyPerm::Use,
424 ];
425 assert!(!v1.includes(v2));
426 assert!(!v2.includes(v1));
427}
428#[test]
429fn key_perm_set_include_no_overlap_test() {
430 let v1 = key_perm_set![KeyPerm::ManageBlob, KeyPerm::Delete, KeyPerm::Grant,];
431 let v2 = key_perm_set![KeyPerm::ReqForcedOp, KeyPerm::Rebind, KeyPerm::Update, KeyPerm::Use,];
432 assert!(!v1.includes(v2));
433 assert!(!v2.includes(v1));
434}