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 android_system_keystore2::aidl::android::system::keystore2::{
22 Domain::Domain, KeyDescriptor::KeyDescriptor, KeyPermission::KeyPermission,
23 };
24
25 use std::cmp::PartialEq;
26 use std::convert::From;
27 use std::ffi::CStr;
28
29 use crate::error::Error as KsError;
30 use keystore2_selinux as selinux;
31
32 use anyhow::Context as AnyhowContext;
33
34 use selinux::Backend;
35
36 use lazy_static::lazy_static;
37
38 // Replace getcon with a mock in the test situation
39 #[cfg(not(test))]
40 use selinux::getcon;
41 #[cfg(test)]
42 use tests::test_getcon as getcon;
43
44 lazy_static! {
45 // Panicking here is allowed because keystore cannot function without this backend
46 // and it would happen early and indicate a gross misconfiguration of the device.
47 static ref KEYSTORE2_KEY_LABEL_BACKEND: selinux::KeystoreKeyBackend =
48 selinux::KeystoreKeyBackend::new().unwrap();
49 }
50
lookup_keystore2_key_context(namespace: i64) -> anyhow::Result<selinux::Context>51 fn lookup_keystore2_key_context(namespace: i64) -> anyhow::Result<selinux::Context> {
52 KEYSTORE2_KEY_LABEL_BACKEND.lookup(&namespace.to_string())
53 }
54
55 /// ## Background
56 ///
57 /// AIDL enums are represented as constants of the form:
58 /// ```
59 /// mod EnumName {
60 /// pub type EnumName = i32;
61 /// pub const Variant1: EnumName = <value1>;
62 /// pub const Variant2: EnumName = <value2>;
63 /// ...
64 /// }
65 ///```
66 /// This macro wraps the enum in a new type, e.g., `MyPerm` and maps each variant to an SELinux
67 /// permission while providing the following interface:
68 /// * From<EnumName> and Into<EnumName> are implemented. Where the implementation of From maps
69 /// any variant not specified to the default.
70 /// * Every variant has a constructor with a name corresponding to its lower case SELinux string
71 /// representation.
72 /// * `MyPerm.to_selinux(&self)` returns the SELinux string representation of the
73 /// represented permission.
74 ///
75 /// ## Special behavior
76 /// If the keyword `use` appears as an selinux name `use_` is used as identifier for the
77 /// constructor function (e.g. `MePerm::use_()`) but the string returned by `to_selinux` will
78 /// still be `"use"`.
79 ///
80 /// ## Example
81 /// ```
82 ///
83 /// implement_permission!(
84 /// /// MyPerm documentation.
85 /// #[derive(Clone, Copy, Debug, PartialEq)]
86 /// MyPerm from EnumName with default (None, none) {}
87 /// Variant1, selinux name: variant1;
88 /// Variant2, selinux name: variant1;
89 /// }
90 /// );
91 /// ```
92 macro_rules! implement_permission_aidl {
93 // This rule provides the public interface of the macro. And starts the preprocessing
94 // recursion (see below).
95 ($(#[$m:meta])* $name:ident from $aidl_name:ident with default ($($def:tt)*)
96 { $($element:tt)* })
97 => {
98 implement_permission_aidl!(@replace_use $($m)*, $name, $aidl_name, ($($def)*), [],
99 $($element)*);
100 };
101
102 // The following three rules recurse through the elements of the form
103 // `<enum variant>, selinux name: <selinux_name>;`
104 // preprocessing the input.
105
106 // The first rule terminates the recursion and passes the processed arguments to the final
107 // rule that spills out the implementation.
108 (@replace_use $($m:meta)*, $name:ident, $aidl_name:ident, ($($def:tt)*), [$($out:tt)*], ) => {
109 implement_permission_aidl!(@end $($m)*, $name, $aidl_name, ($($def)*) { $($out)* } );
110 };
111
112 // The second rule is triggered if the selinux name of an element is literally `use`.
113 // It produces the tuple `<enum variant>, use_, use;`
114 // and appends it to the out list.
115 (@replace_use $($m:meta)*, $name:ident, $aidl_name:ident, ($($def:tt)*), [$($out:tt)*],
116 $e_name:ident, selinux name: use; $($element:tt)*)
117 => {
118 implement_permission_aidl!(@replace_use $($m)*, $name, $aidl_name, ($($def)*),
119 [$($out)* $e_name, use_, use;], $($element)*);
120 };
121
122 // The third rule is the default rule which replaces every input tuple with
123 // `<enum variant>, <selinux_name>, <selinux_name>;`
124 // and appends the result to the out list.
125 (@replace_use $($m:meta)*, $name:ident, $aidl_name:ident, ($($def:tt)*), [$($out:tt)*],
126 $e_name:ident, selinux name: $e_str:ident; $($element:tt)*)
127 => {
128 implement_permission_aidl!(@replace_use $($m)*, $name, $aidl_name, ($($def)*),
129 [$($out)* $e_name, $e_str, $e_str;], $($element)*);
130 };
131
132 (@end $($m:meta)*, $name:ident, $aidl_name:ident,
133 ($def_name:ident, $def_selinux_name:ident) {
134 $($element_name:ident, $element_identifier:ident,
135 $selinux_name:ident;)*
136 })
137 =>
138 {
139 $(#[$m])*
140 pub struct $name(pub $aidl_name);
141
142 impl From<$aidl_name> for $name {
143 fn from (p: $aidl_name) -> Self {
144 match p {
145 $aidl_name::$def_name => Self($aidl_name::$def_name),
146 $($aidl_name::$element_name => Self($aidl_name::$element_name),)*
147 _ => Self($aidl_name::$def_name),
148 }
149 }
150 }
151
152 impl From<$name> for $aidl_name {
153 fn from(p: $name) -> $aidl_name {
154 p.0
155 }
156 }
157
158 impl $name {
159 /// Returns a string representation of the permission as required by
160 /// `selinux::check_access`.
161 pub fn to_selinux(&self) -> &'static str {
162 match self {
163 Self($aidl_name::$def_name) => stringify!($def_selinux_name),
164 $(Self($aidl_name::$element_name) => stringify!($selinux_name),)*
165 _ => stringify!($def_selinux_name),
166 }
167 }
168
169 /// Creates an instance representing a permission with the same name.
170 pub const fn $def_selinux_name() -> Self { Self($aidl_name::$def_name) }
171 $(
172 /// Creates an instance representing a permission with the same name.
173 pub const fn $element_identifier() -> Self { Self($aidl_name::$element_name) }
174 )*
175 }
176 };
177 }
178
179 implement_permission_aidl!(
180 /// KeyPerm provides a convenient abstraction from the SELinux class `keystore2_key`.
181 /// At the same time it maps `KeyPermissions` from the Keystore 2.0 AIDL Grant interface to
182 /// the SELinux permissions. With the implement_permission macro, we conveniently
183 /// provide mappings between the wire type bit field values, the rust enum and the SELinux
184 /// string representation.
185 ///
186 /// ## Example
187 ///
188 /// In this access check `KeyPerm::get_info().to_selinux()` would return the SELinux representation
189 /// "info".
190 /// ```
191 /// selinux::check_access(source_context, target_context, "keystore2_key",
192 /// KeyPerm::get_info().to_selinux());
193 /// ```
194 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
195 KeyPerm from KeyPermission with default (NONE, none) {
196 CONVERT_STORAGE_KEY_TO_EPHEMERAL, selinux name: convert_storage_key_to_ephemeral;
197 DELETE, selinux name: delete;
198 GEN_UNIQUE_ID, selinux name: gen_unique_id;
199 GET_INFO, selinux name: get_info;
200 GRANT, selinux name: grant;
201 MANAGE_BLOB, selinux name: manage_blob;
202 REBIND, selinux name: rebind;
203 REQ_FORCED_OP, selinux name: req_forced_op;
204 UPDATE, selinux name: update;
205 USE, selinux name: use;
206 USE_DEV_ID, selinux name: use_dev_id;
207 }
208 );
209
210 /// This macro implements an enum with values mapped to SELinux permission names.
211 /// The below example wraps the enum MyPermission in the tuple struct `MyPerm` and implements
212 /// * From<i32> and Into<i32> are implemented. Where the implementation of From maps
213 /// any variant not specified to the default.
214 /// * Every variant has a constructor with a name corresponding to its lower case SELinux string
215 /// representation.
216 /// * `MyPerm.to_selinux(&self)` returns the SELinux string representation of the
217 /// represented permission.
218 ///
219 /// ## Example
220 /// ```
221 /// implement_permission!(
222 /// /// MyPerm documentation.
223 /// #[derive(Clone, Copy, Debug, Eq, PartialEq)]
224 /// MyPerm with default (None = 0, none) {
225 /// Foo = 1, selinux name: foo;
226 /// Bar = 2, selinux name: bar;
227 /// }
228 /// );
229 /// ```
230 macro_rules! implement_permission {
231 // This rule provides the public interface of the macro. And starts the preprocessing
232 // recursion (see below).
233 ($(#[$m:meta])* $name:ident with default
234 ($def_name:ident = $def_val:expr, $def_selinux_name:ident)
235 {
236 $($(#[$element_meta:meta])*
237 $element_name:ident = $element_val:expr, selinux name: $selinux_name:ident;)*
238 })
239 => {
240 $(#[$m])*
241 pub enum $name {
242 /// The default variant of an enum.
243 $def_name = $def_val,
244 $(
245 $(#[$element_meta])*
246 $element_name = $element_val,
247 )*
248 }
249
250 impl From<i32> for $name {
251 fn from (p: i32) -> Self {
252 match p {
253 $def_val => Self::$def_name,
254 $($element_val => Self::$element_name,)*
255 _ => Self::$def_name,
256 }
257 }
258 }
259
260 impl From<$name> for i32 {
261 fn from(p: $name) -> i32 {
262 p as i32
263 }
264 }
265
266 impl $name {
267 /// Returns a string representation of the permission as required by
268 /// `selinux::check_access`.
269 pub fn to_selinux(&self) -> &'static str {
270 match self {
271 Self::$def_name => stringify!($def_selinux_name),
272 $(Self::$element_name => stringify!($selinux_name),)*
273 }
274 }
275
276 /// Creates an instance representing a permission with the same name.
277 pub const fn $def_selinux_name() -> Self { Self::$def_name }
278 $(
279 /// Creates an instance representing a permission with the same name.
280 pub const fn $selinux_name() -> Self { Self::$element_name }
281 )*
282 }
283 };
284 }
285
286 implement_permission!(
287 /// KeystorePerm provides a convenient abstraction from the SELinux class `keystore2`.
288 /// Using the implement_permission macro we get the same features as `KeyPerm`.
289 #[derive(Clone, Copy, Debug, PartialEq)]
290 KeystorePerm with default (None = 0, none) {
291 /// Checked when a new auth token is installed.
292 AddAuth = 1, selinux name: add_auth;
293 /// Checked when an app is uninstalled or wiped.
294 ClearNs = 2, selinux name: clear_ns;
295 /// Checked when the user state is queried from Keystore 2.0.
296 GetState = 4, selinux name: get_state;
297 /// Checked when Keystore 2.0 is asked to list a namespace that the caller
298 /// does not have the get_info permission for.
299 List = 8, selinux name: list;
300 /// Checked when Keystore 2.0 gets locked.
301 Lock = 0x10, selinux name: lock;
302 /// Checked when Keystore 2.0 shall be reset.
303 Reset = 0x20, selinux name: reset;
304 /// Checked when Keystore 2.0 shall be unlocked.
305 Unlock = 0x40, selinux name: unlock;
306 /// Checked when user is added or removed.
307 ChangeUser = 0x80, selinux name: change_user;
308 /// Checked when password of the user is changed.
309 ChangePassword = 0x100, selinux name: change_password;
310 /// Checked when a UID is cleared.
311 ClearUID = 0x200, selinux name: clear_uid;
312 /// Checked when Credstore calls IKeystoreAuthorization to obtain auth tokens.
313 GetAuthToken = 0x400, selinux name: get_auth_token;
314 /// Checked when earlyBootEnded() is called.
315 EarlyBootEnded = 0x800, selinux name: early_boot_ended;
316 /// Checked when IKeystoreMaintenance::onDeviceOffBody is called.
317 ReportOffBody = 0x1000, selinux name: report_off_body;
318 /// Checked when IkeystoreMetrics::pullMetris is called.
319 PullMetrics = 0x2000, selinux name: pull_metrics;
320 /// Checked when IKeystoreMaintenance::deleteAllKeys is called.
321 DeleteAllKeys = 0x4000, selinux name: delete_all_keys;
322 }
323 );
324
325 /// Represents a set of `KeyPerm` permissions.
326 /// `IntoIterator` is implemented for this struct allowing the iteration through all the
327 /// permissions in the set.
328 /// It also implements a function `includes(self, other)` that checks if the permissions
329 /// in `other` are included in `self`.
330 ///
331 /// KeyPermSet can be created with the macro `key_perm_set![]`.
332 ///
333 /// ## Example
334 /// ```
335 /// let perms1 = key_perm_set![KeyPerm::use_(), KeyPerm::manage_blob(), KeyPerm::grant()];
336 /// let perms2 = key_perm_set![KeyPerm::use_(), KeyPerm::manage_blob()];
337 ///
338 /// assert!(perms1.includes(perms2))
339 /// assert!(!perms2.includes(perms1))
340 ///
341 /// let i = perms1.into_iter();
342 /// // iteration in ascending order of the permission's numeric representation.
343 /// assert_eq(Some(KeyPerm::manage_blob()), i.next());
344 /// assert_eq(Some(KeyPerm::grant()), i.next());
345 /// assert_eq(Some(KeyPerm::use_()), i.next());
346 /// assert_eq(None, i.next());
347 /// ```
348 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
349 pub struct KeyPermSet(pub i32);
350
351 mod perm {
352 use super::*;
353
354 pub struct IntoIter {
355 vec: KeyPermSet,
356 pos: u8,
357 }
358
359 impl IntoIter {
new(v: KeyPermSet) -> Self360 pub fn new(v: KeyPermSet) -> Self {
361 Self { vec: v, pos: 0 }
362 }
363 }
364
365 impl std::iter::Iterator for IntoIter {
366 type Item = KeyPerm;
367
next(&mut self) -> Option<Self::Item>368 fn next(&mut self) -> Option<Self::Item> {
369 loop {
370 if self.pos == 32 {
371 return None;
372 }
373 let p = self.vec.0 & (1 << self.pos);
374 self.pos += 1;
375 if p != 0 {
376 return Some(KeyPerm::from(KeyPermission(p)));
377 }
378 }
379 }
380 }
381 }
382
383 impl From<KeyPerm> for KeyPermSet {
from(p: KeyPerm) -> Self384 fn from(p: KeyPerm) -> Self {
385 Self((p.0).0 as i32)
386 }
387 }
388
389 /// allow conversion from the AIDL wire type i32 to a permission set.
390 impl From<i32> for KeyPermSet {
from(p: i32) -> Self391 fn from(p: i32) -> Self {
392 Self(p)
393 }
394 }
395
396 impl From<KeyPermSet> for i32 {
from(p: KeyPermSet) -> i32397 fn from(p: KeyPermSet) -> i32 {
398 p.0
399 }
400 }
401
402 impl KeyPermSet {
403 /// Returns true iff this permission set has all of the permissions that are in `other`.
includes<T: Into<KeyPermSet>>(&self, other: T) -> bool404 pub fn includes<T: Into<KeyPermSet>>(&self, other: T) -> bool {
405 let o: KeyPermSet = other.into();
406 (self.0 & o.0) == o.0
407 }
408 }
409
410 /// This macro can be used to create a `KeyPermSet` from a list of `KeyPerm` values.
411 ///
412 /// ## Example
413 /// ```
414 /// let v = key_perm_set![Perm::delete(), Perm::manage_blob()];
415 /// ```
416 #[macro_export]
417 macro_rules! key_perm_set {
418 () => { KeyPermSet(0) };
419 ($head:expr $(, $tail:expr)* $(,)?) => {
420 KeyPermSet(($head.0).0 $(| ($tail.0).0)*)
421 };
422 }
423
424 impl IntoIterator for KeyPermSet {
425 type Item = KeyPerm;
426 type IntoIter = perm::IntoIter;
427
into_iter(self) -> Self::IntoIter428 fn into_iter(self) -> Self::IntoIter {
429 Self::IntoIter::new(self)
430 }
431 }
432
433 /// Uses `selinux::check_access` to check if the given caller context `caller_cxt` may access
434 /// the given permision `perm` of the `keystore2` security class.
check_keystore_permission(caller_ctx: &CStr, perm: KeystorePerm) -> anyhow::Result<()>435 pub fn check_keystore_permission(caller_ctx: &CStr, perm: KeystorePerm) -> anyhow::Result<()> {
436 let target_context = getcon().context("check_keystore_permission: getcon failed.")?;
437 selinux::check_access(caller_ctx, &target_context, "keystore2", perm.to_selinux())
438 }
439
440 /// Uses `selinux::check_access` to check if the given caller context `caller_cxt` has
441 /// all the permissions indicated in `access_vec` for the target domain indicated by the key
442 /// descriptor `key` in the security class `keystore2_key`.
443 ///
444 /// Also checks if the caller has the grant permission for the given target domain.
445 ///
446 /// Attempts to grant the grant permission are always denied.
447 ///
448 /// The only viable target domains are
449 /// * `Domain::APP` in which case u:r:keystore:s0 is used as target context and
450 /// * `Domain::SELINUX` in which case the `key.nspace` parameter is looked up in
451 /// SELinux keystore key backend, and the result is used
452 /// as target context.
check_grant_permission( caller_ctx: &CStr, access_vec: KeyPermSet, key: &KeyDescriptor, ) -> anyhow::Result<()>453 pub fn check_grant_permission(
454 caller_ctx: &CStr,
455 access_vec: KeyPermSet,
456 key: &KeyDescriptor,
457 ) -> anyhow::Result<()> {
458 let target_context = match key.domain {
459 Domain::APP => getcon().context("check_grant_permission: getcon failed.")?,
460 Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
461 .context("check_grant_permission: Domain::SELINUX: Failed to lookup namespace.")?,
462 _ => return Err(KsError::sys()).context(format!("Cannot grant {:?}.", key.domain)),
463 };
464
465 selinux::check_access(caller_ctx, &target_context, "keystore2_key", "grant")
466 .context("Grant permission is required when granting.")?;
467
468 if access_vec.includes(KeyPerm::grant()) {
469 return Err(selinux::Error::perm()).context("Grant permission cannot be granted.");
470 }
471
472 for p in access_vec.into_iter() {
473 selinux::check_access(caller_ctx, &target_context, "keystore2_key", p.to_selinux())
474 .context(format!(
475 concat!(
476 "check_grant_permission: check_access failed. ",
477 "The caller may have tried to grant a permission that they don't possess. {:?}"
478 ),
479 p
480 ))?
481 }
482 Ok(())
483 }
484
485 /// Uses `selinux::check_access` to check if the given caller context `caller_cxt`
486 /// has the permissions indicated by `perm` for the target domain indicated by the key
487 /// descriptor `key` in the security class `keystore2_key`.
488 ///
489 /// The behavior differs slightly depending on the selected target domain:
490 /// * `Domain::APP` u:r:keystore:s0 is used as target context.
491 /// * `Domain::SELINUX` `key.nspace` parameter is looked up in the SELinux keystore key
492 /// backend, and the result is used as target context.
493 /// * `Domain::BLOB` Same as SELinux but the "manage_blob" permission is always checked additionally
494 /// to the one supplied in `perm`.
495 /// * `Domain::GRANT` Does not use selinux::check_access. Instead the `access_vector`
496 /// parameter is queried for permission, which must be supplied in this case.
497 ///
498 /// ## Return values.
499 /// * Ok(()) If the requested permissions were granted.
500 /// * Err(selinux::Error::perm()) If the requested permissions were denied.
501 /// * Err(KsError::sys()) This error is produced if `Domain::GRANT` is selected but no `access_vec`
502 /// was supplied. It is also produced if `Domain::KEY_ID` was selected, and
503 /// on various unexpected backend failures.
check_key_permission( caller_uid: u32, caller_ctx: &CStr, perm: KeyPerm, key: &KeyDescriptor, access_vector: &Option<KeyPermSet>, ) -> anyhow::Result<()>504 pub fn check_key_permission(
505 caller_uid: u32,
506 caller_ctx: &CStr,
507 perm: KeyPerm,
508 key: &KeyDescriptor,
509 access_vector: &Option<KeyPermSet>,
510 ) -> anyhow::Result<()> {
511 // If an access vector was supplied, the key is either accessed by GRANT or by KEY_ID.
512 // In the former case, key.domain was set to GRANT and we check the failure cases
513 // further below. If the access is requested by KEY_ID, key.domain would have been
514 // resolved to APP or SELINUX depending on where the key actually resides.
515 // Either way we can return here immediately if the access vector covers the requested
516 // permission. If it does not, we can still check if the caller has access by means of
517 // ownership.
518 if let Some(access_vector) = access_vector {
519 if access_vector.includes(perm) {
520 return Ok(());
521 }
522 }
523
524 let target_context = match key.domain {
525 // apps get the default keystore context
526 Domain::APP => {
527 if caller_uid as i64 != key.nspace {
528 return Err(selinux::Error::perm())
529 .context("Trying to access key without ownership.");
530 }
531 getcon().context("check_key_permission: getcon failed.")?
532 }
533 Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
534 .context("check_key_permission: Domain::SELINUX: Failed to lookup namespace.")?,
535 Domain::GRANT => {
536 match access_vector {
537 Some(_) => {
538 return Err(selinux::Error::perm())
539 .context(format!("\"{}\" not granted", perm.to_selinux()));
540 }
541 None => {
542 // If DOMAIN_GRANT was selected an access vector must be supplied.
543 return Err(KsError::sys()).context(
544 "Cannot check permission for Domain::GRANT without access vector.",
545 );
546 }
547 }
548 }
549 Domain::KEY_ID => {
550 // We should never be called with `Domain::KEY_ID. The database
551 // lookup should have converted this into one of `Domain::APP`
552 // or `Domain::SELINUX`.
553 return Err(KsError::sys()).context("Cannot check permission for Domain::KEY_ID.");
554 }
555 Domain::BLOB => {
556 let tctx = lookup_keystore2_key_context(key.nspace)
557 .context("Domain::BLOB: Failed to lookup namespace.")?;
558 // If DOMAIN_KEY_BLOB was specified, we check for the "manage_blob"
559 // permission in addition to the requested permission.
560 selinux::check_access(
561 caller_ctx,
562 &tctx,
563 "keystore2_key",
564 KeyPerm::manage_blob().to_selinux(),
565 )?;
566
567 tctx
568 }
569 _ => {
570 return Err(KsError::sys())
571 .context(format!("Unknown domain value: \"{:?}\".", key.domain))
572 }
573 };
574
575 selinux::check_access(caller_ctx, &target_context, "keystore2_key", perm.to_selinux())
576 }
577
578 #[cfg(test)]
579 mod tests {
580 use super::*;
581 use anyhow::anyhow;
582 use anyhow::Result;
583 use keystore2_selinux::*;
584
585 const ALL_PERMS: KeyPermSet = key_perm_set![
586 KeyPerm::manage_blob(),
587 KeyPerm::delete(),
588 KeyPerm::use_dev_id(),
589 KeyPerm::req_forced_op(),
590 KeyPerm::gen_unique_id(),
591 KeyPerm::grant(),
592 KeyPerm::get_info(),
593 KeyPerm::rebind(),
594 KeyPerm::update(),
595 KeyPerm::use_(),
596 KeyPerm::convert_storage_key_to_ephemeral(),
597 ];
598
599 const SYSTEM_SERVER_PERMISSIONS_NO_GRANT: KeyPermSet = key_perm_set![
600 KeyPerm::delete(),
601 KeyPerm::use_dev_id(),
602 // No KeyPerm::grant()
603 KeyPerm::get_info(),
604 KeyPerm::rebind(),
605 KeyPerm::update(),
606 KeyPerm::use_(),
607 ];
608
609 const NOT_GRANT_PERMS: KeyPermSet = key_perm_set![
610 KeyPerm::manage_blob(),
611 KeyPerm::delete(),
612 KeyPerm::use_dev_id(),
613 KeyPerm::req_forced_op(),
614 KeyPerm::gen_unique_id(),
615 // No KeyPerm::grant()
616 KeyPerm::get_info(),
617 KeyPerm::rebind(),
618 KeyPerm::update(),
619 KeyPerm::use_(),
620 KeyPerm::convert_storage_key_to_ephemeral(),
621 ];
622
623 const UNPRIV_PERMS: KeyPermSet = key_perm_set![
624 KeyPerm::delete(),
625 KeyPerm::get_info(),
626 KeyPerm::rebind(),
627 KeyPerm::update(),
628 KeyPerm::use_(),
629 ];
630
631 /// The su_key namespace as defined in su.te and keystore_key_contexts of the
632 /// SePolicy (system/sepolicy).
633 const SU_KEY_NAMESPACE: i32 = 0;
634 /// The shell_key namespace as defined in shell.te and keystore_key_contexts of the
635 /// SePolicy (system/sepolicy).
636 const SHELL_KEY_NAMESPACE: i32 = 1;
637
test_getcon() -> Result<Context>638 pub fn test_getcon() -> Result<Context> {
639 Context::new("u:object_r:keystore:s0")
640 }
641
642 // This macro evaluates the given expression and checks that
643 // a) evaluated to Result::Err() and that
644 // b) the wrapped error is selinux::Error::perm() (permission denied).
645 // We use a macro here because a function would mask which invocation caused the failure.
646 //
647 // TODO b/164121720 Replace this macro with a function when `track_caller` is available.
648 macro_rules! assert_perm_failed {
649 ($test_function:expr) => {
650 let result = $test_function;
651 assert!(result.is_err(), "Permission check should have failed.");
652 assert_eq!(
653 Some(&selinux::Error::perm()),
654 result.err().unwrap().root_cause().downcast_ref::<selinux::Error>()
655 );
656 };
657 }
658
check_context() -> Result<(selinux::Context, i32, bool)>659 fn check_context() -> Result<(selinux::Context, i32, bool)> {
660 // Calling the non mocked selinux::getcon here intended.
661 let context = selinux::getcon()?;
662 match context.to_str().unwrap() {
663 "u:r:su:s0" => Ok((context, SU_KEY_NAMESPACE, true)),
664 "u:r:shell:s0" => Ok((context, SHELL_KEY_NAMESPACE, false)),
665 c => Err(anyhow!(format!(
666 "This test must be run as \"su\" or \"shell\". Current context: \"{}\"",
667 c
668 ))),
669 }
670 }
671
672 #[test]
check_keystore_permission_test() -> Result<()>673 fn check_keystore_permission_test() -> Result<()> {
674 let system_server_ctx = Context::new("u:r:system_server:s0")?;
675 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::add_auth()).is_ok());
676 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::clear_ns()).is_ok());
677 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::get_state()).is_ok());
678 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::lock()).is_ok());
679 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::reset()).is_ok());
680 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::unlock()).is_ok());
681 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::change_user()).is_ok());
682 assert!(
683 check_keystore_permission(&system_server_ctx, KeystorePerm::change_password()).is_ok()
684 );
685 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::clear_uid()).is_ok());
686 let shell_ctx = Context::new("u:r:shell:s0")?;
687 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::add_auth()));
688 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::clear_ns()));
689 assert!(check_keystore_permission(&shell_ctx, KeystorePerm::get_state()).is_ok());
690 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::list()));
691 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::lock()));
692 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::reset()));
693 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::unlock()));
694 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::change_user()));
695 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::change_password()));
696 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::clear_uid()));
697 Ok(())
698 }
699
700 #[test]
check_grant_permission_app() -> Result<()>701 fn check_grant_permission_app() -> Result<()> {
702 let system_server_ctx = Context::new("u:r:system_server:s0")?;
703 let shell_ctx = Context::new("u:r:shell:s0")?;
704 let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
705 check_grant_permission(&system_server_ctx, SYSTEM_SERVER_PERMISSIONS_NO_GRANT, &key)
706 .expect("Grant permission check failed.");
707
708 // attempts to grant the grant permission must always fail even when privileged.
709 assert_perm_failed!(check_grant_permission(
710 &system_server_ctx,
711 KeyPerm::grant().into(),
712 &key
713 ));
714 // unprivileged grant attempts always fail. shell does not have the grant permission.
715 assert_perm_failed!(check_grant_permission(&shell_ctx, UNPRIV_PERMS, &key));
716 Ok(())
717 }
718
719 #[test]
check_grant_permission_selinux() -> Result<()>720 fn check_grant_permission_selinux() -> Result<()> {
721 let (sctx, namespace, is_su) = check_context()?;
722 let key = KeyDescriptor {
723 domain: Domain::SELINUX,
724 nspace: namespace as i64,
725 alias: None,
726 blob: None,
727 };
728 if is_su {
729 assert!(check_grant_permission(&sctx, NOT_GRANT_PERMS, &key).is_ok());
730 // attempts to grant the grant permission must always fail even when privileged.
731 assert_perm_failed!(check_grant_permission(&sctx, KeyPerm::grant().into(), &key));
732 } else {
733 // unprivileged grant attempts always fail. shell does not have the grant permission.
734 assert_perm_failed!(check_grant_permission(&sctx, UNPRIV_PERMS, &key));
735 }
736 Ok(())
737 }
738
739 #[test]
check_key_permission_domain_grant() -> Result<()>740 fn check_key_permission_domain_grant() -> Result<()> {
741 let key = KeyDescriptor { domain: Domain::GRANT, nspace: 0, alias: None, blob: None };
742
743 assert_perm_failed!(check_key_permission(
744 0,
745 &selinux::Context::new("ignored").unwrap(),
746 KeyPerm::grant(),
747 &key,
748 &Some(UNPRIV_PERMS)
749 ));
750
751 check_key_permission(
752 0,
753 &selinux::Context::new("ignored").unwrap(),
754 KeyPerm::use_(),
755 &key,
756 &Some(ALL_PERMS),
757 )
758 }
759
760 #[test]
check_key_permission_domain_app() -> Result<()>761 fn check_key_permission_domain_app() -> Result<()> {
762 let system_server_ctx = Context::new("u:r:system_server:s0")?;
763 let shell_ctx = Context::new("u:r:shell:s0")?;
764 let gmscore_app = Context::new("u:r:gmscore_app:s0")?;
765
766 let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
767
768 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::use_(), &key, &None).is_ok());
769 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::delete(), &key, &None).is_ok());
770 assert!(
771 check_key_permission(0, &system_server_ctx, KeyPerm::get_info(), &key, &None).is_ok()
772 );
773 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::rebind(), &key, &None).is_ok());
774 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::update(), &key, &None).is_ok());
775 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::grant(), &key, &None).is_ok());
776 assert!(
777 check_key_permission(0, &system_server_ctx, KeyPerm::use_dev_id(), &key, &None).is_ok()
778 );
779 assert!(
780 check_key_permission(0, &gmscore_app, KeyPerm::gen_unique_id(), &key, &None).is_ok()
781 );
782
783 assert!(check_key_permission(0, &shell_ctx, KeyPerm::use_(), &key, &None).is_ok());
784 assert!(check_key_permission(0, &shell_ctx, KeyPerm::delete(), &key, &None).is_ok());
785 assert!(check_key_permission(0, &shell_ctx, KeyPerm::get_info(), &key, &None).is_ok());
786 assert!(check_key_permission(0, &shell_ctx, KeyPerm::rebind(), &key, &None).is_ok());
787 assert!(check_key_permission(0, &shell_ctx, KeyPerm::update(), &key, &None).is_ok());
788 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::grant(), &key, &None));
789 assert_perm_failed!(check_key_permission(
790 0,
791 &shell_ctx,
792 KeyPerm::req_forced_op(),
793 &key,
794 &None
795 ));
796 assert_perm_failed!(check_key_permission(
797 0,
798 &shell_ctx,
799 KeyPerm::manage_blob(),
800 &key,
801 &None
802 ));
803 assert_perm_failed!(check_key_permission(
804 0,
805 &shell_ctx,
806 KeyPerm::use_dev_id(),
807 &key,
808 &None
809 ));
810 assert_perm_failed!(check_key_permission(
811 0,
812 &shell_ctx,
813 KeyPerm::gen_unique_id(),
814 &key,
815 &None
816 ));
817
818 // Also make sure that the permission fails if the caller is not the owner.
819 assert_perm_failed!(check_key_permission(
820 1, // the owner is 0
821 &system_server_ctx,
822 KeyPerm::use_(),
823 &key,
824 &None
825 ));
826 // Unless there was a grant.
827 assert!(check_key_permission(
828 1,
829 &system_server_ctx,
830 KeyPerm::use_(),
831 &key,
832 &Some(key_perm_set![KeyPerm::use_()])
833 )
834 .is_ok());
835 // But fail if the grant did not cover the requested permission.
836 assert_perm_failed!(check_key_permission(
837 1,
838 &system_server_ctx,
839 KeyPerm::use_(),
840 &key,
841 &Some(key_perm_set![KeyPerm::get_info()])
842 ));
843
844 Ok(())
845 }
846
847 #[test]
check_key_permission_domain_selinux() -> Result<()>848 fn check_key_permission_domain_selinux() -> Result<()> {
849 let (sctx, namespace, is_su) = check_context()?;
850 let key = KeyDescriptor {
851 domain: Domain::SELINUX,
852 nspace: namespace as i64,
853 alias: None,
854 blob: None,
855 };
856
857 if is_su {
858 assert!(check_key_permission(0, &sctx, KeyPerm::use_(), &key, &None).is_ok());
859 assert!(check_key_permission(0, &sctx, KeyPerm::delete(), &key, &None).is_ok());
860 assert!(check_key_permission(0, &sctx, KeyPerm::get_info(), &key, &None).is_ok());
861 assert!(check_key_permission(0, &sctx, KeyPerm::rebind(), &key, &None).is_ok());
862 assert!(check_key_permission(0, &sctx, KeyPerm::update(), &key, &None).is_ok());
863 assert!(check_key_permission(0, &sctx, KeyPerm::grant(), &key, &None).is_ok());
864 assert!(check_key_permission(0, &sctx, KeyPerm::manage_blob(), &key, &None).is_ok());
865 assert!(check_key_permission(0, &sctx, KeyPerm::use_dev_id(), &key, &None).is_ok());
866 assert!(check_key_permission(0, &sctx, KeyPerm::gen_unique_id(), &key, &None).is_ok());
867 assert!(check_key_permission(0, &sctx, KeyPerm::req_forced_op(), &key, &None).is_ok());
868 } else {
869 assert!(check_key_permission(0, &sctx, KeyPerm::use_(), &key, &None).is_ok());
870 assert!(check_key_permission(0, &sctx, KeyPerm::delete(), &key, &None).is_ok());
871 assert!(check_key_permission(0, &sctx, KeyPerm::get_info(), &key, &None).is_ok());
872 assert!(check_key_permission(0, &sctx, KeyPerm::rebind(), &key, &None).is_ok());
873 assert!(check_key_permission(0, &sctx, KeyPerm::update(), &key, &None).is_ok());
874 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::grant(), &key, &None));
875 assert_perm_failed!(check_key_permission(
876 0,
877 &sctx,
878 KeyPerm::req_forced_op(),
879 &key,
880 &None
881 ));
882 assert_perm_failed!(check_key_permission(
883 0,
884 &sctx,
885 KeyPerm::manage_blob(),
886 &key,
887 &None
888 ));
889 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::use_dev_id(), &key, &None));
890 assert_perm_failed!(check_key_permission(
891 0,
892 &sctx,
893 KeyPerm::gen_unique_id(),
894 &key,
895 &None
896 ));
897 }
898 Ok(())
899 }
900
901 #[test]
check_key_permission_domain_blob() -> Result<()>902 fn check_key_permission_domain_blob() -> Result<()> {
903 let (sctx, namespace, is_su) = check_context()?;
904 let key = KeyDescriptor {
905 domain: Domain::BLOB,
906 nspace: namespace as i64,
907 alias: None,
908 blob: None,
909 };
910
911 if is_su {
912 check_key_permission(0, &sctx, KeyPerm::use_(), &key, &None)
913 } else {
914 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::use_(), &key, &None));
915 Ok(())
916 }
917 }
918
919 #[test]
check_key_permission_domain_key_id() -> Result<()>920 fn check_key_permission_domain_key_id() -> Result<()> {
921 let key = KeyDescriptor { domain: Domain::KEY_ID, nspace: 0, alias: None, blob: None };
922
923 assert_eq!(
924 Some(&KsError::sys()),
925 check_key_permission(
926 0,
927 &selinux::Context::new("ignored").unwrap(),
928 KeyPerm::use_(),
929 &key,
930 &None
931 )
932 .err()
933 .unwrap()
934 .root_cause()
935 .downcast_ref::<KsError>()
936 );
937 Ok(())
938 }
939
940 #[test]
key_perm_set_all_test()941 fn key_perm_set_all_test() {
942 let v = key_perm_set![
943 KeyPerm::manage_blob(),
944 KeyPerm::delete(),
945 KeyPerm::use_dev_id(),
946 KeyPerm::req_forced_op(),
947 KeyPerm::gen_unique_id(),
948 KeyPerm::grant(),
949 KeyPerm::get_info(),
950 KeyPerm::rebind(),
951 KeyPerm::update(),
952 KeyPerm::use_() // Test if the macro accepts missing comma at the end of the list.
953 ];
954 let mut i = v.into_iter();
955 assert_eq!(i.next().unwrap().to_selinux(), "delete");
956 assert_eq!(i.next().unwrap().to_selinux(), "gen_unique_id");
957 assert_eq!(i.next().unwrap().to_selinux(), "get_info");
958 assert_eq!(i.next().unwrap().to_selinux(), "grant");
959 assert_eq!(i.next().unwrap().to_selinux(), "manage_blob");
960 assert_eq!(i.next().unwrap().to_selinux(), "rebind");
961 assert_eq!(i.next().unwrap().to_selinux(), "req_forced_op");
962 assert_eq!(i.next().unwrap().to_selinux(), "update");
963 assert_eq!(i.next().unwrap().to_selinux(), "use");
964 assert_eq!(i.next().unwrap().to_selinux(), "use_dev_id");
965 assert_eq!(None, i.next());
966 }
967 #[test]
key_perm_set_sparse_test()968 fn key_perm_set_sparse_test() {
969 let v = key_perm_set![
970 KeyPerm::manage_blob(),
971 KeyPerm::req_forced_op(),
972 KeyPerm::gen_unique_id(),
973 KeyPerm::update(),
974 KeyPerm::use_(), // Test if macro accepts the comma at the end of the list.
975 ];
976 let mut i = v.into_iter();
977 assert_eq!(i.next().unwrap().to_selinux(), "gen_unique_id");
978 assert_eq!(i.next().unwrap().to_selinux(), "manage_blob");
979 assert_eq!(i.next().unwrap().to_selinux(), "req_forced_op");
980 assert_eq!(i.next().unwrap().to_selinux(), "update");
981 assert_eq!(i.next().unwrap().to_selinux(), "use");
982 assert_eq!(None, i.next());
983 }
984 #[test]
key_perm_set_empty_test()985 fn key_perm_set_empty_test() {
986 let v = key_perm_set![];
987 let mut i = v.into_iter();
988 assert_eq!(None, i.next());
989 }
990 #[test]
key_perm_set_include_subset_test()991 fn key_perm_set_include_subset_test() {
992 let v1 = key_perm_set![
993 KeyPerm::manage_blob(),
994 KeyPerm::delete(),
995 KeyPerm::use_dev_id(),
996 KeyPerm::req_forced_op(),
997 KeyPerm::gen_unique_id(),
998 KeyPerm::grant(),
999 KeyPerm::get_info(),
1000 KeyPerm::rebind(),
1001 KeyPerm::update(),
1002 KeyPerm::use_(),
1003 ];
1004 let v2 = key_perm_set![
1005 KeyPerm::manage_blob(),
1006 KeyPerm::delete(),
1007 KeyPerm::rebind(),
1008 KeyPerm::update(),
1009 KeyPerm::use_(),
1010 ];
1011 assert!(v1.includes(v2));
1012 assert!(!v2.includes(v1));
1013 }
1014 #[test]
key_perm_set_include_equal_test()1015 fn key_perm_set_include_equal_test() {
1016 let v1 = key_perm_set![
1017 KeyPerm::manage_blob(),
1018 KeyPerm::delete(),
1019 KeyPerm::rebind(),
1020 KeyPerm::update(),
1021 KeyPerm::use_(),
1022 ];
1023 let v2 = key_perm_set![
1024 KeyPerm::manage_blob(),
1025 KeyPerm::delete(),
1026 KeyPerm::rebind(),
1027 KeyPerm::update(),
1028 KeyPerm::use_(),
1029 ];
1030 assert!(v1.includes(v2));
1031 assert!(v2.includes(v1));
1032 }
1033 #[test]
key_perm_set_include_overlap_test()1034 fn key_perm_set_include_overlap_test() {
1035 let v1 = key_perm_set![
1036 KeyPerm::manage_blob(),
1037 KeyPerm::delete(),
1038 KeyPerm::grant(), // only in v1
1039 KeyPerm::rebind(),
1040 KeyPerm::update(),
1041 KeyPerm::use_(),
1042 ];
1043 let v2 = key_perm_set![
1044 KeyPerm::manage_blob(),
1045 KeyPerm::delete(),
1046 KeyPerm::req_forced_op(), // only in v2
1047 KeyPerm::rebind(),
1048 KeyPerm::update(),
1049 KeyPerm::use_(),
1050 ];
1051 assert!(!v1.includes(v2));
1052 assert!(!v2.includes(v1));
1053 }
1054 #[test]
key_perm_set_include_no_overlap_test()1055 fn key_perm_set_include_no_overlap_test() {
1056 let v1 = key_perm_set![KeyPerm::manage_blob(), KeyPerm::delete(), KeyPerm::grant(),];
1057 let v2 = key_perm_set![
1058 KeyPerm::req_forced_op(),
1059 KeyPerm::rebind(),
1060 KeyPerm::update(),
1061 KeyPerm::use_(),
1062 ];
1063 assert!(!v1.includes(v2));
1064 assert!(!v2.includes(v1));
1065 }
1066 }
1067