Fix partition verification
Switch from a denylist to an allowlist for the selinux labels of disk
partitions. Fix the code to match against type rather than the full
label. Extend the list of exempted partitions. Add a unit test (and
delete the redundant placeholder test). Simplify SeContext since we no
longer need to construct one from a string, add the ability to extract
the type.
Along the way, I improved error reporting to give the full context for
errors (otherwise the interesting bits get omitted).
Bug: 237054515
Test: atest MicrodroidHostTestCases ComposHostTestCases
Test: test virtualizationservice_device_test
Change-Id: Ia3993a9b783b1f31bc5312af40dd5a17bf4ebfb0
diff --git a/virtualizationservice/src/selinux.rs b/virtualizationservice/src/selinux.rs
index e450dee..0485943 100644
--- a/virtualizationservice/src/selinux.rs
+++ b/virtualizationservice/src/selinux.rs
@@ -14,7 +14,7 @@
//! Wrapper to libselinux
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, bail, Context, Result};
use std::ffi::{CStr, CString};
use std::fmt;
use std::fs::File;
@@ -30,6 +30,7 @@
/// `freecon` to free the resources when dropped. In its second variant it stores
/// an `std::ffi::CString` that can be initialized from a Rust string slice.
#[derive(Debug)]
+#[allow(dead_code)] // CString variant is used in tests
pub enum SeContext {
/// Wraps a raw context c-string as returned by libselinux.
Raw(*mut ::std::os::raw::c_char),
@@ -78,12 +79,27 @@
impl SeContext {
/// Initializes the `SeContext::CString` variant from a Rust string slice.
+ #[allow(dead_code)] // Used in tests
pub fn new(con: &str) -> Result<Self> {
Ok(Self::CString(
CString::new(con)
.with_context(|| format!("Failed to create SeContext with \"{}\"", con))?,
))
}
+
+ pub fn selinux_type(&self) -> Result<&str> {
+ let context = self.deref().to_str().context("Label is not valid UTF8")?;
+
+ // The syntax is user:role:type:sensitivity[:category,...],
+ // ignoring security level ranges, which don't occur on Android. See
+ // https://github.com/SELinuxProject/selinux-notebook/blob/main/src/security_context.md
+ // We only want the type.
+ let fields: Vec<_> = context.split(':').collect();
+ if fields.len() < 4 || fields.len() > 5 {
+ bail!("Syntactically invalid label {}", self);
+ }
+ Ok(fields[2])
+ }
}
pub fn getfilecon(file: &File) -> Result<SeContext> {