virtmngr: get secontext of the caller app

This patch uses getprevcon from libselinux to get the secontext of the
caller process (i.e. the process that "owns" the VM).

Since virtmngr is started by the "VM owner" process by forking+execing
virtmngr process as a child, we can make use of the getprevcon function
in the libselinux. This function returns the secontext before the last
exec.

In this patch we simply log the callers secontext, in the follow up
patches the callers secontext will be used to check if the VM is allowed
to access the requested secure services.

Bug: 360102915
Test: atest MicrodroidTests
Change-Id: Ia484c6e44efd703ace1eb2f6f72675e153dfa5a4
diff --git a/android/virtmgr/src/aidl.rs b/android/virtmgr/src/aidl.rs
index 9d72506..cc7cf7c 100644
--- a/android/virtmgr/src/aidl.rs
+++ b/android/virtmgr/src/aidl.rs
@@ -21,7 +21,7 @@
 use crate::debug_config::DebugConfig;
 use crate::dt_overlay::{create_device_tree_overlay, VM_DT_OVERLAY_MAX_SIZE, VM_DT_OVERLAY_PATH};
 use crate::payload::{add_microdroid_payload_images, add_microdroid_system_images, add_microdroid_vendor_image};
-use crate::selinux::{getfilecon, SeContext};
+use crate::selinux::{getfilecon, getprevcon, SeContext};
 use android_os_permissions_aidl::aidl::android::os::IPermissionController;
 use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon::{
     Certificate::Certificate,
@@ -502,6 +502,9 @@
             check_config_allowed_for_early_vms(config)?;
         }
 
+        let caller_secontext = getprevcon().or_service_specific_exception(-1)?;
+        info!("callers secontext: {}", caller_secontext);
+
         // Allocating VM context checks the MANAGE_VIRTUAL_MACHINE permission.
         let (vm_context, cid, temporary_directory) = if cfg!(early) {
             self.create_early_vm_context(config)?
diff --git a/android/virtmgr/src/selinux.rs b/android/virtmgr/src/selinux.rs
index ba62b7f..284cd23 100644
--- a/android/virtmgr/src/selinux.rs
+++ b/android/virtmgr/src/selinux.rs
@@ -117,3 +117,19 @@
         _ => Err(anyhow!(io::Error::last_os_error())).context("fgetfilecon failed"),
     }
 }
+
+pub fn getprevcon() -> Result<SeContext> {
+    let mut con: *mut c_char = ptr::null_mut();
+    // SAFETY: the returned pointer `con` is wrapped in SeContext::Raw which is freed with
+    // `freecon` when it is dropped.
+    match unsafe { selinux_bindgen::getprevcon(&mut con) } {
+        0.. => {
+            if !con.is_null() {
+                Ok(SeContext::Raw(con))
+            } else {
+                Err(anyhow!("getprevcon returned a NULL context"))
+            }
+        }
+        _ => Err(anyhow!(io::Error::last_os_error())).context("getprevcon failed"),
+    }
+}