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