1 // 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 //! This crate provides access control primitives for Keystore 2.0.
16 //! It provides high level functions for checking permissions in the keystore2 and keystore2_key
17 //! SELinux classes based on the keystore2_selinux backend.
18 //! It also provides KeystorePerm and KeyPerm as convenience wrappers for the SELinux permission
19 //! defined by keystore2 and keystore2_key respectively.
20
21 use crate::error::Error as KsError;
22 use crate::error::ResponseCode;
23 use crate::ks_err;
24 use android_system_keystore2::aidl::android::system::keystore2::{
25 Domain::Domain, KeyDescriptor::KeyDescriptor, KeyPermission::KeyPermission,
26 };
27 use anyhow::Context as AnyhowContext;
28 use keystore2_selinux as selinux;
29 use lazy_static::lazy_static;
30 use selinux::{implement_class, Backend, ClassPermission};
31 use std::cmp::PartialEq;
32 use std::convert::From;
33 use std::ffi::CStr;
34
35 // Replace getcon with a mock in the test situation
36 #[cfg(not(test))]
37 use selinux::getcon;
38 #[cfg(test)]
39 use tests::test_getcon as getcon;
40
41 lazy_static! {
42 // Panicking here is allowed because keystore cannot function without this backend
43 // and it would happen early and indicate a gross misconfiguration of the device.
44 static ref KEYSTORE2_KEY_LABEL_BACKEND: selinux::KeystoreKeyBackend =
45 selinux::KeystoreKeyBackend::new().unwrap();
46 }
47
lookup_keystore2_key_context(namespace: i64) -> anyhow::Result<selinux::Context>48 fn lookup_keystore2_key_context(namespace: i64) -> anyhow::Result<selinux::Context> {
49 KEYSTORE2_KEY_LABEL_BACKEND.lookup(&namespace.to_string())
50 }
51
52 implement_class!(
53 /// KeyPerm provides a convenient abstraction from the SELinux class `keystore2_key`.
54 /// At the same time it maps `KeyPermissions` from the Keystore 2.0 AIDL Grant interface to
55 /// the SELinux permissions.
56 #[repr(i32)]
57 #[selinux(class_name = keystore2_key)]
58 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
59 pub enum KeyPerm {
60 /// Checked when convert_storage_key_to_ephemeral is called.
61 #[selinux(name = convert_storage_key_to_ephemeral)]
62 ConvertStorageKeyToEphemeral = KeyPermission::CONVERT_STORAGE_KEY_TO_EPHEMERAL.0,
63 /// Checked when the caller tries do delete a key.
64 #[selinux(name = delete)]
65 Delete = KeyPermission::DELETE.0,
66 /// Checked when the caller tries to use a unique id.
67 #[selinux(name = gen_unique_id)]
68 GenUniqueId = KeyPermission::GEN_UNIQUE_ID.0,
69 /// Checked when the caller tries to load a key.
70 #[selinux(name = get_info)]
71 GetInfo = KeyPermission::GET_INFO.0,
72 /// Checked when the caller attempts to grant a key to another uid.
73 /// Also used for gating key migration attempts.
74 #[selinux(name = grant)]
75 Grant = KeyPermission::GRANT.0,
76 /// Checked when the caller attempts to use Domain::BLOB.
77 #[selinux(name = manage_blob)]
78 ManageBlob = KeyPermission::MANAGE_BLOB.0,
79 /// Checked when the caller tries to create a key which implies rebinding
80 /// an alias to the new key.
81 #[selinux(name = rebind)]
82 Rebind = KeyPermission::REBIND.0,
83 /// Checked when the caller attempts to create a forced operation.
84 #[selinux(name = req_forced_op)]
85 ReqForcedOp = KeyPermission::REQ_FORCED_OP.0,
86 /// Checked when the caller attempts to update public key artifacts.
87 #[selinux(name = update)]
88 Update = KeyPermission::UPDATE.0,
89 /// Checked when the caller attempts to use a private or public key.
90 #[selinux(name = use)]
91 Use = KeyPermission::USE.0,
92 /// Does nothing, and is not checked. For use of device identifiers,
93 /// the caller must hold the READ_PRIVILEGED_PHONE_STATE Android
94 /// permission.
95 #[selinux(name = use_dev_id)]
96 UseDevId = KeyPermission::USE_DEV_ID.0,
97 }
98 );
99
100 implement_class!(
101 /// KeystorePerm provides a convenient abstraction from the SELinux class `keystore2`.
102 /// Using the implement_permission macro we get the same features as `KeyPerm`.
103 #[selinux(class_name = keystore2)]
104 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
105 pub enum KeystorePerm {
106 /// Checked when a new auth token is installed.
107 #[selinux(name = add_auth)]
108 AddAuth,
109 /// Checked when an app is uninstalled or wiped.
110 #[selinux(name = clear_ns)]
111 ClearNs,
112 /// Checked when Keystore 2.0 is asked to list a namespace that the caller
113 /// does not have the get_info permission for.
114 #[selinux(name = list)]
115 List,
116 /// Checked when Keystore 2.0 gets locked.
117 #[selinux(name = lock)]
118 Lock,
119 /// Checked when Keystore 2.0 shall be reset.
120 #[selinux(name = reset)]
121 Reset,
122 /// Checked when Keystore 2.0 shall be unlocked.
123 #[selinux(name = unlock)]
124 Unlock,
125 /// Checked when user is added or removed.
126 #[selinux(name = change_user)]
127 ChangeUser,
128 /// Checked when password of the user is changed.
129 #[selinux(name = change_password)]
130 ChangePassword,
131 /// Checked when a UID is cleared.
132 #[selinux(name = clear_uid)]
133 ClearUID,
134 /// Checked when Credstore calls IKeystoreAuthorization to obtain auth tokens.
135 #[selinux(name = get_auth_token)]
136 GetAuthToken,
137 /// Checked when earlyBootEnded() is called.
138 #[selinux(name = early_boot_ended)]
139 EarlyBootEnded,
140 /// Checked when IKeystoreMetrics::pullMetrics is called.
141 #[selinux(name = pull_metrics)]
142 PullMetrics,
143 /// Checked when IKeystoreMaintenance::deleteAllKeys is called.
144 #[selinux(name = delete_all_keys)]
145 DeleteAllKeys,
146 /// Checked on calls to IRemotelyProvisionedKeyPool::getAttestationKey
147 #[selinux(name = get_attestation_key)]
148 GetAttestationKey,
149 /// Checked on IKeystoreAuthorization::getLastAuthTime() is called.
150 #[selinux(name = get_last_auth_time)]
151 GetLastAuthTime,
152 }
153 );
154
155 /// Represents a set of `KeyPerm` permissions.
156 /// `IntoIterator` is implemented for this struct allowing the iteration through all the
157 /// permissions in the set.
158 /// It also implements a function `includes(self, other)` that checks if the permissions
159 /// in `other` are included in `self`.
160 ///
161 /// KeyPermSet can be created with the macro `key_perm_set![]`.
162 ///
163 /// ## Example
164 /// ```
165 /// let perms1 = key_perm_set![KeyPerm::Use, KeyPerm::ManageBlob, KeyPerm::Grant];
166 /// let perms2 = key_perm_set![KeyPerm::Use, KeyPerm::ManageBlob];
167 ///
168 /// assert!(perms1.includes(perms2))
169 /// assert!(!perms2.includes(perms1))
170 ///
171 /// let i = perms1.into_iter();
172 /// // iteration in ascending order of the permission's numeric representation.
173 /// assert_eq(Some(KeyPerm::ManageBlob), i.next());
174 /// assert_eq(Some(KeyPerm::Grant), i.next());
175 /// assert_eq(Some(KeyPerm::Use), i.next());
176 /// assert_eq(None, i.next());
177 /// ```
178 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
179 pub struct KeyPermSet(pub i32);
180
181 mod perm {
182 use super::*;
183
184 pub struct IntoIter {
185 vec: KeyPermSet,
186 pos: u8,
187 }
188
189 impl IntoIter {
new(v: KeyPermSet) -> Self190 pub fn new(v: KeyPermSet) -> Self {
191 Self { vec: v, pos: 0 }
192 }
193 }
194
195 impl std::iter::Iterator for IntoIter {
196 type Item = KeyPerm;
197
next(&mut self) -> Option<Self::Item>198 fn next(&mut self) -> Option<Self::Item> {
199 loop {
200 if self.pos == 32 {
201 return None;
202 }
203 let p = self.vec.0 & (1 << self.pos);
204 self.pos += 1;
205 if p != 0 {
206 return Some(KeyPerm::from(p));
207 }
208 }
209 }
210 }
211 }
212
213 impl From<KeyPerm> for KeyPermSet {
from(p: KeyPerm) -> Self214 fn from(p: KeyPerm) -> Self {
215 Self(p as i32)
216 }
217 }
218
219 /// allow conversion from the AIDL wire type i32 to a permission set.
220 impl From<i32> for KeyPermSet {
from(p: i32) -> Self221 fn from(p: i32) -> Self {
222 Self(p)
223 }
224 }
225
226 impl From<KeyPermSet> for i32 {
from(p: KeyPermSet) -> i32227 fn from(p: KeyPermSet) -> i32 {
228 p.0
229 }
230 }
231
232 impl KeyPermSet {
233 /// Returns true iff this permission set has all of the permissions that are in `other`.
includes<T: Into<KeyPermSet>>(&self, other: T) -> bool234 pub fn includes<T: Into<KeyPermSet>>(&self, other: T) -> bool {
235 let o: KeyPermSet = other.into();
236 (self.0 & o.0) == o.0
237 }
238 }
239
240 /// This macro can be used to create a `KeyPermSet` from a list of `KeyPerm` values.
241 ///
242 /// ## Example
243 /// ```
244 /// let v = key_perm_set![Perm::delete(), Perm::manage_blob()];
245 /// ```
246 #[macro_export]
247 macro_rules! key_perm_set {
248 () => { KeyPermSet(0) };
249 ($head:expr $(, $tail:expr)* $(,)?) => {
250 KeyPermSet($head as i32 $(| $tail as i32)*)
251 };
252 }
253
254 impl IntoIterator for KeyPermSet {
255 type Item = KeyPerm;
256 type IntoIter = perm::IntoIter;
257
into_iter(self) -> Self::IntoIter258 fn into_iter(self) -> Self::IntoIter {
259 Self::IntoIter::new(self)
260 }
261 }
262
263 /// Uses `selinux::check_permission` to check if the given caller context `caller_cxt` may access
264 /// the given permision `perm` of the `keystore2` security class.
check_keystore_permission(caller_ctx: &CStr, perm: KeystorePerm) -> anyhow::Result<()>265 pub fn check_keystore_permission(caller_ctx: &CStr, perm: KeystorePerm) -> anyhow::Result<()> {
266 let target_context = getcon().context("check_keystore_permission: getcon failed.")?;
267 selinux::check_permission(caller_ctx, &target_context, perm)
268 }
269
270 /// Uses `selinux::check_permission` to check if the given caller context `caller_cxt` has
271 /// all the permissions indicated in `access_vec` for the target domain indicated by the key
272 /// descriptor `key` in the security class `keystore2_key`.
273 ///
274 /// Also checks if the caller has the grant permission for the given target domain.
275 ///
276 /// Attempts to grant the grant permission are always denied.
277 ///
278 /// The only viable target domains are
279 /// * `Domain::APP` in which case u:r:keystore:s0 is used as target context and
280 /// * `Domain::SELINUX` in which case the `key.nspace` parameter is looked up in
281 /// SELinux keystore key backend, and the result is used
282 /// as target context.
check_grant_permission( caller_ctx: &CStr, access_vec: KeyPermSet, key: &KeyDescriptor, ) -> anyhow::Result<()>283 pub fn check_grant_permission(
284 caller_ctx: &CStr,
285 access_vec: KeyPermSet,
286 key: &KeyDescriptor,
287 ) -> anyhow::Result<()> {
288 let target_context = match key.domain {
289 Domain::APP => getcon().context("check_grant_permission: getcon failed.")?,
290 Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
291 .context("check_grant_permission: Domain::SELINUX: Failed to lookup namespace.")?,
292 _ => return Err(KsError::sys()).context(format!("Cannot grant {:?}.", key.domain)),
293 };
294
295 selinux::check_permission(caller_ctx, &target_context, KeyPerm::Grant)
296 .context("Grant permission is required when granting.")?;
297
298 if access_vec.includes(KeyPerm::Grant) {
299 return Err(selinux::Error::perm()).context("Grant permission cannot be granted.");
300 }
301
302 for p in access_vec.into_iter() {
303 selinux::check_permission(caller_ctx, &target_context, p).context(ks_err!(
304 "check_permission failed. \
305 The caller may have tried to grant a permission that they don't possess. {:?}",
306 p
307 ))?
308 }
309 Ok(())
310 }
311
312 /// Uses `selinux::check_permission` to check if the given caller context `caller_cxt`
313 /// has the permissions indicated by `perm` for the target domain indicated by the key
314 /// descriptor `key` in the security class `keystore2_key`.
315 ///
316 /// The behavior differs slightly depending on the selected target domain:
317 /// * `Domain::APP` u:r:keystore:s0 is used as target context.
318 /// * `Domain::SELINUX` `key.nspace` parameter is looked up in the SELinux keystore key
319 /// backend, and the result is used as target context.
320 /// * `Domain::BLOB` Same as SELinux but the "manage_blob" permission is always checked additionally
321 /// to the one supplied in `perm`.
322 /// * `Domain::GRANT` Does not use selinux::check_permission. Instead the `access_vector`
323 /// parameter is queried for permission, which must be supplied in this case.
324 ///
325 /// ## Return values.
326 /// * Ok(()) If the requested permissions were granted.
327 /// * Err(selinux::Error::perm()) If the requested permissions were denied.
328 /// * Err(KsError::sys()) This error is produced if `Domain::GRANT` is selected but no `access_vec`
329 /// was supplied. It is also produced if `Domain::KEY_ID` was selected, and
330 /// on various unexpected backend failures.
check_key_permission( caller_uid: u32, caller_ctx: &CStr, perm: KeyPerm, key: &KeyDescriptor, access_vector: &Option<KeyPermSet>, ) -> anyhow::Result<()>331 pub fn check_key_permission(
332 caller_uid: u32,
333 caller_ctx: &CStr,
334 perm: KeyPerm,
335 key: &KeyDescriptor,
336 access_vector: &Option<KeyPermSet>,
337 ) -> anyhow::Result<()> {
338 // If an access vector was supplied, the key is either accessed by GRANT or by KEY_ID.
339 // In the former case, key.domain was set to GRANT and we check the failure cases
340 // further below. If the access is requested by KEY_ID, key.domain would have been
341 // resolved to APP or SELINUX depending on where the key actually resides.
342 // Either way we can return here immediately if the access vector covers the requested
343 // permission. If it does not, we can still check if the caller has access by means of
344 // ownership.
345 if let Some(access_vector) = access_vector {
346 if access_vector.includes(perm) {
347 return Ok(());
348 }
349 }
350
351 let target_context = match key.domain {
352 // apps get the default keystore context
353 Domain::APP => {
354 if caller_uid as i64 != key.nspace {
355 return Err(selinux::Error::perm())
356 .context("Trying to access key without ownership.");
357 }
358 getcon().context(ks_err!("getcon failed."))?
359 }
360 Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
361 .context(ks_err!("Domain::SELINUX: Failed to lookup namespace."))?,
362 Domain::GRANT => {
363 match access_vector {
364 Some(_) => {
365 return Err(selinux::Error::perm())
366 .context(format!("\"{}\" not granted", perm.name()));
367 }
368 None => {
369 // If DOMAIN_GRANT was selected an access vector must be supplied.
370 return Err(KsError::sys()).context(ks_err!(
371 "Cannot check permission for Domain::GRANT without access vector.",
372 ));
373 }
374 }
375 }
376 Domain::KEY_ID => {
377 // We should never be called with `Domain::KEY_ID. The database
378 // lookup should have converted this into one of `Domain::APP`
379 // or `Domain::SELINUX`.
380 return Err(KsError::sys())
381 .context(ks_err!("Cannot check permission for Domain::KEY_ID.",));
382 }
383 Domain::BLOB => {
384 let tctx = lookup_keystore2_key_context(key.nspace)
385 .context(ks_err!("Domain::BLOB: Failed to lookup namespace."))?;
386 // If DOMAIN_KEY_BLOB was specified, we check for the "manage_blob"
387 // permission in addition to the requested permission.
388 selinux::check_permission(caller_ctx, &tctx, KeyPerm::ManageBlob)?;
389
390 tctx
391 }
392 _ => {
393 return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT))
394 .context(format!("Unknown domain value: \"{:?}\".", key.domain))
395 }
396 };
397
398 selinux::check_permission(caller_ctx, &target_context, perm)
399 }
400
401 #[cfg(test)]
402 mod tests {
403 use super::*;
404 use anyhow::anyhow;
405 use anyhow::Result;
406 use keystore2_selinux::*;
407
408 const ALL_PERMS: KeyPermSet = key_perm_set![
409 KeyPerm::ManageBlob,
410 KeyPerm::Delete,
411 KeyPerm::UseDevId,
412 KeyPerm::ReqForcedOp,
413 KeyPerm::GenUniqueId,
414 KeyPerm::Grant,
415 KeyPerm::GetInfo,
416 KeyPerm::Rebind,
417 KeyPerm::Update,
418 KeyPerm::Use,
419 KeyPerm::ConvertStorageKeyToEphemeral,
420 ];
421
422 const SYSTEM_SERVER_PERMISSIONS_NO_GRANT: KeyPermSet = key_perm_set![
423 KeyPerm::Delete,
424 KeyPerm::UseDevId,
425 // No KeyPerm::Grant
426 KeyPerm::GetInfo,
427 KeyPerm::Rebind,
428 KeyPerm::Update,
429 KeyPerm::Use,
430 ];
431
432 const NOT_GRANT_PERMS: KeyPermSet = key_perm_set![
433 KeyPerm::ManageBlob,
434 KeyPerm::Delete,
435 KeyPerm::UseDevId,
436 KeyPerm::ReqForcedOp,
437 KeyPerm::GenUniqueId,
438 // No KeyPerm::Grant
439 KeyPerm::GetInfo,
440 KeyPerm::Rebind,
441 KeyPerm::Update,
442 KeyPerm::Use,
443 KeyPerm::ConvertStorageKeyToEphemeral,
444 ];
445
446 const UNPRIV_PERMS: KeyPermSet = key_perm_set![
447 KeyPerm::Delete,
448 KeyPerm::GetInfo,
449 KeyPerm::Rebind,
450 KeyPerm::Update,
451 KeyPerm::Use,
452 ];
453
454 /// The su_key namespace as defined in su.te and keystore_key_contexts of the
455 /// SePolicy (system/sepolicy).
456 const SU_KEY_NAMESPACE: i32 = 0;
457 /// The shell_key namespace as defined in shell.te and keystore_key_contexts of the
458 /// SePolicy (system/sepolicy).
459 const SHELL_KEY_NAMESPACE: i32 = 1;
460
test_getcon() -> Result<Context>461 pub fn test_getcon() -> Result<Context> {
462 Context::new("u:object_r:keystore:s0")
463 }
464
465 // This macro evaluates the given expression and checks that
466 // a) evaluated to Result::Err() and that
467 // b) the wrapped error is selinux::Error::perm() (permission denied).
468 // We use a macro here because a function would mask which invocation caused the failure.
469 //
470 // TODO b/164121720 Replace this macro with a function when `track_caller` is available.
471 macro_rules! assert_perm_failed {
472 ($test_function:expr) => {
473 let result = $test_function;
474 assert!(result.is_err(), "Permission check should have failed.");
475 assert_eq!(
476 Some(&selinux::Error::perm()),
477 result.err().unwrap().root_cause().downcast_ref::<selinux::Error>()
478 );
479 };
480 }
481
check_context() -> Result<(selinux::Context, i32, bool)>482 fn check_context() -> Result<(selinux::Context, i32, bool)> {
483 // Calling the non mocked selinux::getcon here intended.
484 let context = selinux::getcon()?;
485 match context.to_str().unwrap() {
486 "u:r:su:s0" => Ok((context, SU_KEY_NAMESPACE, true)),
487 "u:r:shell:s0" => Ok((context, SHELL_KEY_NAMESPACE, false)),
488 c => Err(anyhow!(format!(
489 "This test must be run as \"su\" or \"shell\". Current context: \"{}\"",
490 c
491 ))),
492 }
493 }
494
495 #[test]
check_keystore_permission_test() -> Result<()>496 fn check_keystore_permission_test() -> Result<()> {
497 let system_server_ctx = Context::new("u:r:system_server:s0")?;
498 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::AddAuth).is_ok());
499 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ClearNs).is_ok());
500 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::Lock).is_ok());
501 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::Reset).is_ok());
502 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::Unlock).is_ok());
503 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ChangeUser).is_ok());
504 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ChangePassword).is_ok());
505 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ClearUID).is_ok());
506 let shell_ctx = Context::new("u:r:shell:s0")?;
507 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::AddAuth));
508 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ClearNs));
509 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::List));
510 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::Lock));
511 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::Reset));
512 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::Unlock));
513 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ChangeUser));
514 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ChangePassword));
515 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ClearUID));
516 Ok(())
517 }
518
519 #[test]
check_grant_permission_app() -> Result<()>520 fn check_grant_permission_app() -> Result<()> {
521 let system_server_ctx = Context::new("u:r:system_server:s0")?;
522 let shell_ctx = Context::new("u:r:shell:s0")?;
523 let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
524 check_grant_permission(&system_server_ctx, SYSTEM_SERVER_PERMISSIONS_NO_GRANT, &key)
525 .expect("Grant permission check failed.");
526
527 // attempts to grant the grant permission must always fail even when privileged.
528 assert_perm_failed!(check_grant_permission(
529 &system_server_ctx,
530 KeyPerm::Grant.into(),
531 &key
532 ));
533 // unprivileged grant attempts always fail. shell does not have the grant permission.
534 assert_perm_failed!(check_grant_permission(&shell_ctx, UNPRIV_PERMS, &key));
535 Ok(())
536 }
537
538 #[test]
check_grant_permission_selinux() -> Result<()>539 fn check_grant_permission_selinux() -> Result<()> {
540 let (sctx, namespace, is_su) = check_context()?;
541 let key = KeyDescriptor {
542 domain: Domain::SELINUX,
543 nspace: namespace as i64,
544 alias: None,
545 blob: None,
546 };
547 if is_su {
548 assert!(check_grant_permission(&sctx, NOT_GRANT_PERMS, &key).is_ok());
549 // attempts to grant the grant permission must always fail even when privileged.
550 assert_perm_failed!(check_grant_permission(&sctx, KeyPerm::Grant.into(), &key));
551 } else {
552 // unprivileged grant attempts always fail. shell does not have the grant permission.
553 assert_perm_failed!(check_grant_permission(&sctx, UNPRIV_PERMS, &key));
554 }
555 Ok(())
556 }
557
558 #[test]
check_key_permission_domain_grant() -> Result<()>559 fn check_key_permission_domain_grant() -> Result<()> {
560 let key = KeyDescriptor { domain: Domain::GRANT, nspace: 0, alias: None, blob: None };
561
562 assert_perm_failed!(check_key_permission(
563 0,
564 &selinux::Context::new("ignored").unwrap(),
565 KeyPerm::Grant,
566 &key,
567 &Some(UNPRIV_PERMS)
568 ));
569
570 check_key_permission(
571 0,
572 &selinux::Context::new("ignored").unwrap(),
573 KeyPerm::Use,
574 &key,
575 &Some(ALL_PERMS),
576 )
577 }
578
579 #[test]
check_key_permission_domain_app() -> Result<()>580 fn check_key_permission_domain_app() -> Result<()> {
581 let system_server_ctx = Context::new("u:r:system_server:s0")?;
582 let shell_ctx = Context::new("u:r:shell:s0")?;
583 let gmscore_app = Context::new("u:r:gmscore_app:s0")?;
584
585 let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
586
587 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Use, &key, &None).is_ok());
588 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Delete, &key, &None).is_ok());
589 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::GetInfo, &key, &None).is_ok());
590 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Rebind, &key, &None).is_ok());
591 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Update, &key, &None).is_ok());
592 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Grant, &key, &None).is_ok());
593 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::UseDevId, &key, &None).is_ok());
594 assert!(check_key_permission(0, &gmscore_app, KeyPerm::GenUniqueId, &key, &None).is_ok());
595
596 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Use, &key, &None).is_ok());
597 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Delete, &key, &None).is_ok());
598 assert!(check_key_permission(0, &shell_ctx, KeyPerm::GetInfo, &key, &None).is_ok());
599 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Rebind, &key, &None).is_ok());
600 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Update, &key, &None).is_ok());
601 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::Grant, &key, &None));
602 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::ReqForcedOp, &key, &None));
603 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::ManageBlob, &key, &None));
604 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::UseDevId, &key, &None));
605 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::GenUniqueId, &key, &None));
606
607 // Also make sure that the permission fails if the caller is not the owner.
608 assert_perm_failed!(check_key_permission(
609 1, // the owner is 0
610 &system_server_ctx,
611 KeyPerm::Use,
612 &key,
613 &None
614 ));
615 // Unless there was a grant.
616 assert!(check_key_permission(
617 1,
618 &system_server_ctx,
619 KeyPerm::Use,
620 &key,
621 &Some(key_perm_set![KeyPerm::Use])
622 )
623 .is_ok());
624 // But fail if the grant did not cover the requested permission.
625 assert_perm_failed!(check_key_permission(
626 1,
627 &system_server_ctx,
628 KeyPerm::Use,
629 &key,
630 &Some(key_perm_set![KeyPerm::GetInfo])
631 ));
632
633 Ok(())
634 }
635
636 #[test]
check_key_permission_domain_selinux() -> Result<()>637 fn check_key_permission_domain_selinux() -> Result<()> {
638 let (sctx, namespace, is_su) = check_context()?;
639 let key = KeyDescriptor {
640 domain: Domain::SELINUX,
641 nspace: namespace as i64,
642 alias: None,
643 blob: None,
644 };
645
646 assert!(check_key_permission(0, &sctx, KeyPerm::Use, &key, &None).is_ok());
647 assert!(check_key_permission(0, &sctx, KeyPerm::Delete, &key, &None).is_ok());
648 assert!(check_key_permission(0, &sctx, KeyPerm::GetInfo, &key, &None).is_ok());
649 assert!(check_key_permission(0, &sctx, KeyPerm::Rebind, &key, &None).is_ok());
650 assert!(check_key_permission(0, &sctx, KeyPerm::Update, &key, &None).is_ok());
651
652 if is_su {
653 assert!(check_key_permission(0, &sctx, KeyPerm::Grant, &key, &None).is_ok());
654 assert!(check_key_permission(0, &sctx, KeyPerm::ManageBlob, &key, &None).is_ok());
655 assert!(check_key_permission(0, &sctx, KeyPerm::UseDevId, &key, &None).is_ok());
656 assert!(check_key_permission(0, &sctx, KeyPerm::GenUniqueId, &key, &None).is_ok());
657 assert!(check_key_permission(0, &sctx, KeyPerm::ReqForcedOp, &key, &None).is_ok());
658 } else {
659 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::Grant, &key, &None));
660 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::ReqForcedOp, &key, &None));
661 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::ManageBlob, &key, &None));
662 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::UseDevId, &key, &None));
663 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::GenUniqueId, &key, &None));
664 }
665 Ok(())
666 }
667
668 #[test]
check_key_permission_domain_blob() -> Result<()>669 fn check_key_permission_domain_blob() -> Result<()> {
670 let (sctx, namespace, is_su) = check_context()?;
671 let key = KeyDescriptor {
672 domain: Domain::BLOB,
673 nspace: namespace as i64,
674 alias: None,
675 blob: None,
676 };
677
678 if is_su {
679 check_key_permission(0, &sctx, KeyPerm::Use, &key, &None)
680 } else {
681 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::Use, &key, &None));
682 Ok(())
683 }
684 }
685
686 #[test]
check_key_permission_domain_key_id() -> Result<()>687 fn check_key_permission_domain_key_id() -> Result<()> {
688 let key = KeyDescriptor { domain: Domain::KEY_ID, nspace: 0, alias: None, blob: None };
689
690 assert_eq!(
691 Some(&KsError::sys()),
692 check_key_permission(
693 0,
694 &selinux::Context::new("ignored").unwrap(),
695 KeyPerm::Use,
696 &key,
697 &None
698 )
699 .err()
700 .unwrap()
701 .root_cause()
702 .downcast_ref::<KsError>()
703 );
704 Ok(())
705 }
706
707 #[test]
key_perm_set_all_test()708 fn key_perm_set_all_test() {
709 let v = key_perm_set![
710 KeyPerm::ManageBlob,
711 KeyPerm::Delete,
712 KeyPerm::UseDevId,
713 KeyPerm::ReqForcedOp,
714 KeyPerm::GenUniqueId,
715 KeyPerm::Grant,
716 KeyPerm::GetInfo,
717 KeyPerm::Rebind,
718 KeyPerm::Update,
719 KeyPerm::Use // Test if the macro accepts missing comma at the end of the list.
720 ];
721 let mut i = v.into_iter();
722 assert_eq!(i.next().unwrap().name(), "delete");
723 assert_eq!(i.next().unwrap().name(), "gen_unique_id");
724 assert_eq!(i.next().unwrap().name(), "get_info");
725 assert_eq!(i.next().unwrap().name(), "grant");
726 assert_eq!(i.next().unwrap().name(), "manage_blob");
727 assert_eq!(i.next().unwrap().name(), "rebind");
728 assert_eq!(i.next().unwrap().name(), "req_forced_op");
729 assert_eq!(i.next().unwrap().name(), "update");
730 assert_eq!(i.next().unwrap().name(), "use");
731 assert_eq!(i.next().unwrap().name(), "use_dev_id");
732 assert_eq!(None, i.next());
733 }
734 #[test]
key_perm_set_sparse_test()735 fn key_perm_set_sparse_test() {
736 let v = key_perm_set![
737 KeyPerm::ManageBlob,
738 KeyPerm::ReqForcedOp,
739 KeyPerm::GenUniqueId,
740 KeyPerm::Update,
741 KeyPerm::Use, // Test if macro accepts the comma at the end of the list.
742 ];
743 let mut i = v.into_iter();
744 assert_eq!(i.next().unwrap().name(), "gen_unique_id");
745 assert_eq!(i.next().unwrap().name(), "manage_blob");
746 assert_eq!(i.next().unwrap().name(), "req_forced_op");
747 assert_eq!(i.next().unwrap().name(), "update");
748 assert_eq!(i.next().unwrap().name(), "use");
749 assert_eq!(None, i.next());
750 }
751 #[test]
key_perm_set_empty_test()752 fn key_perm_set_empty_test() {
753 let v = key_perm_set![];
754 let mut i = v.into_iter();
755 assert_eq!(None, i.next());
756 }
757 #[test]
key_perm_set_include_subset_test()758 fn key_perm_set_include_subset_test() {
759 let v1 = key_perm_set![
760 KeyPerm::ManageBlob,
761 KeyPerm::Delete,
762 KeyPerm::UseDevId,
763 KeyPerm::ReqForcedOp,
764 KeyPerm::GenUniqueId,
765 KeyPerm::Grant,
766 KeyPerm::GetInfo,
767 KeyPerm::Rebind,
768 KeyPerm::Update,
769 KeyPerm::Use,
770 ];
771 let v2 = key_perm_set![
772 KeyPerm::ManageBlob,
773 KeyPerm::Delete,
774 KeyPerm::Rebind,
775 KeyPerm::Update,
776 KeyPerm::Use,
777 ];
778 assert!(v1.includes(v2));
779 assert!(!v2.includes(v1));
780 }
781 #[test]
key_perm_set_include_equal_test()782 fn key_perm_set_include_equal_test() {
783 let v1 = key_perm_set![
784 KeyPerm::ManageBlob,
785 KeyPerm::Delete,
786 KeyPerm::Rebind,
787 KeyPerm::Update,
788 KeyPerm::Use,
789 ];
790 let v2 = key_perm_set![
791 KeyPerm::ManageBlob,
792 KeyPerm::Delete,
793 KeyPerm::Rebind,
794 KeyPerm::Update,
795 KeyPerm::Use,
796 ];
797 assert!(v1.includes(v2));
798 assert!(v2.includes(v1));
799 }
800 #[test]
key_perm_set_include_overlap_test()801 fn key_perm_set_include_overlap_test() {
802 let v1 = key_perm_set![
803 KeyPerm::ManageBlob,
804 KeyPerm::Delete,
805 KeyPerm::Grant, // only in v1
806 KeyPerm::Rebind,
807 KeyPerm::Update,
808 KeyPerm::Use,
809 ];
810 let v2 = key_perm_set![
811 KeyPerm::ManageBlob,
812 KeyPerm::Delete,
813 KeyPerm::ReqForcedOp, // only in v2
814 KeyPerm::Rebind,
815 KeyPerm::Update,
816 KeyPerm::Use,
817 ];
818 assert!(!v1.includes(v2));
819 assert!(!v2.includes(v1));
820 }
821 #[test]
key_perm_set_include_no_overlap_test()822 fn key_perm_set_include_no_overlap_test() {
823 let v1 = key_perm_set![KeyPerm::ManageBlob, KeyPerm::Delete, KeyPerm::Grant,];
824 let v2 =
825 key_perm_set![KeyPerm::ReqForcedOp, KeyPerm::Rebind, KeyPerm::Update, KeyPerm::Use,];
826 assert!(!v1.includes(v2));
827 assert!(!v2.includes(v1));
828 }
829 }
830