blob: 68c9b746a248d975e29ba969001d83596cd22ddb [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")?;
David Drysdale2566fb32024-07-09 14:46:37 +0100137 let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
David Drysdale8e92e742024-10-22 13:07:07 +0100138 check_grant_permission(0, &system_server_ctx, SYSTEM_SERVER_PERMISSIONS_NO_GRANT, &key)
David Drysdale2566fb32024-07-09 14:46:37 +0100139 .expect("Grant permission check failed.");
140
141 // attempts to grant the grant permission must always fail even when privileged.
David Drysdale8e92e742024-10-22 13:07:07 +0100142 assert_perm_failed!(check_grant_permission(0, &system_server_ctx, KeyPerm::Grant.into(), &key));
David Drysdale2566fb32024-07-09 14:46:37 +0100143 Ok(())
144}
145
146#[test]
147fn check_grant_permission_selinux() -> Result<()> {
148 let (sctx, namespace, is_su) = check_context()?;
149 let key = KeyDescriptor {
150 domain: Domain::SELINUX,
151 nspace: namespace as i64,
152 alias: None,
153 blob: None,
154 };
155 if is_su {
David Drysdale8e92e742024-10-22 13:07:07 +0100156 assert!(check_grant_permission(0, &sctx, NOT_GRANT_PERMS, &key).is_ok());
David Drysdale2566fb32024-07-09 14:46:37 +0100157 // attempts to grant the grant permission must always fail even when privileged.
David Drysdale8e92e742024-10-22 13:07:07 +0100158 assert_perm_failed!(check_grant_permission(0, &sctx, KeyPerm::Grant.into(), &key));
David Drysdale2566fb32024-07-09 14:46:37 +0100159 } else {
160 // unprivileged grant attempts always fail. shell does not have the grant permission.
David Drysdale8e92e742024-10-22 13:07:07 +0100161 assert_perm_failed!(check_grant_permission(0, &sctx, UNPRIV_PERMS, &key));
David Drysdale2566fb32024-07-09 14:46:37 +0100162 }
163 Ok(())
164}
165
166#[test]
167fn check_key_permission_domain_grant() -> Result<()> {
168 let key = KeyDescriptor { domain: Domain::GRANT, nspace: 0, alias: None, blob: None };
169
170 assert_perm_failed!(check_key_permission(
171 0,
172 &selinux::Context::new("ignored").unwrap(),
173 KeyPerm::Grant,
174 &key,
175 &Some(UNPRIV_PERMS)
176 ));
177
178 check_key_permission(
179 0,
180 &selinux::Context::new("ignored").unwrap(),
181 KeyPerm::Use,
182 &key,
183 &Some(ALL_PERMS),
184 )
185}
186
187#[test]
188fn check_key_permission_domain_app() -> Result<()> {
189 let system_server_ctx = Context::new("u:r:system_server:s0")?;
190 let shell_ctx = Context::new("u:r:shell:s0")?;
191 let gmscore_app = Context::new("u:r:gmscore_app:s0")?;
192
193 let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
194
195 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Use, &key, &None).is_ok());
196 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Delete, &key, &None).is_ok());
197 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::GetInfo, &key, &None).is_ok());
198 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Rebind, &key, &None).is_ok());
199 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Update, &key, &None).is_ok());
200 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Grant, &key, &None).is_ok());
201 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::UseDevId, &key, &None).is_ok());
202 assert!(check_key_permission(0, &gmscore_app, KeyPerm::GenUniqueId, &key, &None).is_ok());
203
204 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Use, &key, &None).is_ok());
205 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Delete, &key, &None).is_ok());
206 assert!(check_key_permission(0, &shell_ctx, KeyPerm::GetInfo, &key, &None).is_ok());
207 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Rebind, &key, &None).is_ok());
208 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Update, &key, &None).is_ok());
David Drysdale2566fb32024-07-09 14:46:37 +0100209 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::ReqForcedOp, &key, &None));
210 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::ManageBlob, &key, &None));
211 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::UseDevId, &key, &None));
212 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::GenUniqueId, &key, &None));
213
214 // Also make sure that the permission fails if the caller is not the owner.
215 assert_perm_failed!(check_key_permission(
216 1, // the owner is 0
217 &system_server_ctx,
218 KeyPerm::Use,
219 &key,
220 &None
221 ));
222 // Unless there was a grant.
223 assert!(check_key_permission(
224 1,
225 &system_server_ctx,
226 KeyPerm::Use,
227 &key,
228 &Some(key_perm_set![KeyPerm::Use])
229 )
230 .is_ok());
231 // But fail if the grant did not cover the requested permission.
232 assert_perm_failed!(check_key_permission(
233 1,
234 &system_server_ctx,
235 KeyPerm::Use,
236 &key,
237 &Some(key_perm_set![KeyPerm::GetInfo])
238 ));
239
240 Ok(())
241}
242
243#[test]
244fn check_key_permission_domain_selinux() -> Result<()> {
245 let (sctx, namespace, is_su) = check_context()?;
246 let key = KeyDescriptor {
247 domain: Domain::SELINUX,
248 nspace: namespace as i64,
249 alias: None,
250 blob: None,
251 };
252
253 assert!(check_key_permission(0, &sctx, KeyPerm::Use, &key, &None).is_ok());
254 assert!(check_key_permission(0, &sctx, KeyPerm::Delete, &key, &None).is_ok());
255 assert!(check_key_permission(0, &sctx, KeyPerm::GetInfo, &key, &None).is_ok());
256 assert!(check_key_permission(0, &sctx, KeyPerm::Rebind, &key, &None).is_ok());
257 assert!(check_key_permission(0, &sctx, KeyPerm::Update, &key, &None).is_ok());
258
259 if is_su {
260 assert!(check_key_permission(0, &sctx, KeyPerm::Grant, &key, &None).is_ok());
261 assert!(check_key_permission(0, &sctx, KeyPerm::ManageBlob, &key, &None).is_ok());
262 assert!(check_key_permission(0, &sctx, KeyPerm::UseDevId, &key, &None).is_ok());
263 assert!(check_key_permission(0, &sctx, KeyPerm::GenUniqueId, &key, &None).is_ok());
264 assert!(check_key_permission(0, &sctx, KeyPerm::ReqForcedOp, &key, &None).is_ok());
265 } else {
266 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::Grant, &key, &None));
267 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::ReqForcedOp, &key, &None));
268 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::ManageBlob, &key, &None));
269 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::UseDevId, &key, &None));
270 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::GenUniqueId, &key, &None));
271 }
272 Ok(())
273}
274
275#[test]
276fn check_key_permission_domain_blob() -> Result<()> {
277 let (sctx, namespace, is_su) = check_context()?;
278 let key =
279 KeyDescriptor { domain: Domain::BLOB, nspace: namespace as i64, alias: None, blob: None };
280
281 if is_su {
282 check_key_permission(0, &sctx, KeyPerm::Use, &key, &None)
283 } else {
284 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::Use, &key, &None));
285 Ok(())
286 }
287}
288
289#[test]
290fn check_key_permission_domain_key_id() -> Result<()> {
291 let key = KeyDescriptor { domain: Domain::KEY_ID, nspace: 0, alias: None, blob: None };
292
293 assert_eq!(
294 Some(&KsError::sys()),
295 check_key_permission(
296 0,
297 &selinux::Context::new("ignored").unwrap(),
298 KeyPerm::Use,
299 &key,
300 &None
301 )
302 .err()
303 .unwrap()
304 .root_cause()
305 .downcast_ref::<KsError>()
306 );
307 Ok(())
308}
309
310#[test]
311fn key_perm_set_all_test() {
312 let v = key_perm_set![
313 KeyPerm::ManageBlob,
314 KeyPerm::Delete,
315 KeyPerm::UseDevId,
316 KeyPerm::ReqForcedOp,
317 KeyPerm::GenUniqueId,
318 KeyPerm::Grant,
319 KeyPerm::GetInfo,
320 KeyPerm::Rebind,
321 KeyPerm::Update,
322 KeyPerm::Use // Test if the macro accepts missing comma at the end of the list.
323 ];
324 let mut i = v.into_iter();
325 assert_eq!(i.next().unwrap().name(), "delete");
326 assert_eq!(i.next().unwrap().name(), "gen_unique_id");
327 assert_eq!(i.next().unwrap().name(), "get_info");
328 assert_eq!(i.next().unwrap().name(), "grant");
329 assert_eq!(i.next().unwrap().name(), "manage_blob");
330 assert_eq!(i.next().unwrap().name(), "rebind");
331 assert_eq!(i.next().unwrap().name(), "req_forced_op");
332 assert_eq!(i.next().unwrap().name(), "update");
333 assert_eq!(i.next().unwrap().name(), "use");
334 assert_eq!(i.next().unwrap().name(), "use_dev_id");
335 assert_eq!(None, i.next());
336}
337#[test]
338fn key_perm_set_sparse_test() {
339 let v = key_perm_set![
340 KeyPerm::ManageBlob,
341 KeyPerm::ReqForcedOp,
342 KeyPerm::GenUniqueId,
343 KeyPerm::Update,
344 KeyPerm::Use, // Test if macro accepts the comma at the end of the list.
345 ];
346 let mut i = v.into_iter();
347 assert_eq!(i.next().unwrap().name(), "gen_unique_id");
348 assert_eq!(i.next().unwrap().name(), "manage_blob");
349 assert_eq!(i.next().unwrap().name(), "req_forced_op");
350 assert_eq!(i.next().unwrap().name(), "update");
351 assert_eq!(i.next().unwrap().name(), "use");
352 assert_eq!(None, i.next());
353}
354#[test]
355fn key_perm_set_empty_test() {
356 let v = key_perm_set![];
357 let mut i = v.into_iter();
358 assert_eq!(None, i.next());
359}
360#[test]
361fn key_perm_set_include_subset_test() {
362 let v1 = key_perm_set![
363 KeyPerm::ManageBlob,
364 KeyPerm::Delete,
365 KeyPerm::UseDevId,
366 KeyPerm::ReqForcedOp,
367 KeyPerm::GenUniqueId,
368 KeyPerm::Grant,
369 KeyPerm::GetInfo,
370 KeyPerm::Rebind,
371 KeyPerm::Update,
372 KeyPerm::Use,
373 ];
374 let v2 = key_perm_set![
375 KeyPerm::ManageBlob,
376 KeyPerm::Delete,
377 KeyPerm::Rebind,
378 KeyPerm::Update,
379 KeyPerm::Use,
380 ];
381 assert!(v1.includes(v2));
382 assert!(!v2.includes(v1));
383}
384#[test]
385fn key_perm_set_include_equal_test() {
386 let v1 = key_perm_set![
387 KeyPerm::ManageBlob,
388 KeyPerm::Delete,
389 KeyPerm::Rebind,
390 KeyPerm::Update,
391 KeyPerm::Use,
392 ];
393 let v2 = key_perm_set![
394 KeyPerm::ManageBlob,
395 KeyPerm::Delete,
396 KeyPerm::Rebind,
397 KeyPerm::Update,
398 KeyPerm::Use,
399 ];
400 assert!(v1.includes(v2));
401 assert!(v2.includes(v1));
402}
403#[test]
404fn key_perm_set_include_overlap_test() {
405 let v1 = key_perm_set![
406 KeyPerm::ManageBlob,
407 KeyPerm::Delete,
408 KeyPerm::Grant, // only in v1
409 KeyPerm::Rebind,
410 KeyPerm::Update,
411 KeyPerm::Use,
412 ];
413 let v2 = key_perm_set![
414 KeyPerm::ManageBlob,
415 KeyPerm::Delete,
416 KeyPerm::ReqForcedOp, // only in v2
417 KeyPerm::Rebind,
418 KeyPerm::Update,
419 KeyPerm::Use,
420 ];
421 assert!(!v1.includes(v2));
422 assert!(!v2.includes(v1));
423}
424#[test]
425fn key_perm_set_include_no_overlap_test() {
426 let v1 = key_perm_set![KeyPerm::ManageBlob, KeyPerm::Delete, KeyPerm::Grant,];
427 let v2 = key_perm_set![KeyPerm::ReqForcedOp, KeyPerm::Rebind, KeyPerm::Update, KeyPerm::Use,];
428 assert!(!v1.includes(v2));
429 assert!(!v2.includes(v1));
430}