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