Merge "Revert "[VirtMgr] Allow host-controlled avf/untrusted prop"" into main
diff --git a/virtualizationmanager/src/aidl.rs b/virtualizationmanager/src/aidl.rs
index d9d10ea..771863b 100644
--- a/virtualizationmanager/src/aidl.rs
+++ b/virtualizationmanager/src/aidl.rs
@@ -19,9 +19,9 @@
 use crate::composite::make_composite_image;
 use crate::crosvm::{CrosvmConfig, DiskFile, PayloadState, VmContext, VmInstance, VmState};
 use crate::debug_config::DebugConfig;
-use crate::dt_overlay::{create_device_tree_overlay, DtAddition, VM_REFERENCE_DT_ON_HOST_PATH, 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::reference_dt;
 use android_os_permissions_aidl::aidl::android::os::IPermissionController;
 use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon::{
     Certificate::Certificate,
@@ -68,7 +68,6 @@
     Status, StatusCode, Strong,
     IntoBinderResult,
 };
-use cstr::cstr;
 use disk::QcowFile;
 use glob::glob;
 use lazy_static::lazy_static;
@@ -80,7 +79,6 @@
 use semver::VersionReq;
 use std::collections::HashSet;
 use std::convert::TryInto;
-use std::fs;
 use std::ffi::CStr;
 use std::fs::{canonicalize, read_dir, remove_file, File, OpenOptions};
 use std::io::{BufRead, BufReader, Error, ErrorKind, Seek, SeekFrom, Write};
@@ -378,35 +376,13 @@
             check_gdb_allowed(config)?;
         }
 
-        // Currently, VirtMgr adds the host copy of reference DT & an untrusted prop (instance-id)
-        let mut dt_additions = Vec::with_capacity(2);
-        let host_ref_dt = Path::new(VM_REFERENCE_DT_ON_HOST_PATH);
-        if host_ref_dt.exists()
-            && read_dir(host_ref_dt).or_service_specific_exception(-1)?.next().is_some()
-        {
-            dt_additions.push(DtAddition::FromPath(host_ref_dt));
-        } else {
-            warn!("VM reference DT doesn't exist in host DT");
+        let reference_dt = reference_dt::parse_reference_dt(&temporary_directory)
+            .context("Failed to create VM reference DT")
+            .or_service_specific_exception(-1)?;
+        if reference_dt.is_none() {
+            warn!("VM reference DT doesn't exist");
         }
 
-        if cfg!(llpvm_changes) {
-            // TODO(b/291213394): Replace this with a per-VM instance Id.
-            let instance_id = b"sixtyfourbyteslonghardcoded_indeed_sixtyfourbyteslonghardcoded_h";
-            dt_additions.push(DtAddition::AvfUntrustedProp(cstr!("instance-id"), &instance_id[..]));
-        }
-
-        let device_tree_overlay = if !dt_additions.is_empty() {
-            let dt_output = temporary_directory.join(VM_DT_OVERLAY_PATH);
-            let mut data = [0_u8; VM_DT_OVERLAY_MAX_SIZE];
-            let fdt = create_device_tree_overlay(&mut data, &dt_additions)
-                .map_err(|e| anyhow!("Failed to create DT overlay, {e:?}"))
-                .or_service_specific_exception(-1)?;
-            fs::write(&dt_output, fdt.as_slice()).or_service_specific_exception(-1)?;
-            Some(File::open(dt_output).or_service_specific_exception(-1)?)
-        } else {
-            None
-        };
-
         let debug_level = match config {
             VirtualMachineConfig::AppConfig(config) => config.debugLevel,
             _ => DebugLevel::NONE,
@@ -555,7 +531,7 @@
             gdb_port,
             vfio_devices,
             dtbo,
-            device_tree_overlay,
+            reference_dt,
         };
         let instance = Arc::new(
             VmInstance::new(
diff --git a/virtualizationmanager/src/crosvm.rs b/virtualizationmanager/src/crosvm.rs
index 2c23441..84c60bd 100644
--- a/virtualizationmanager/src/crosvm.rs
+++ b/virtualizationmanager/src/crosvm.rs
@@ -118,7 +118,7 @@
     pub gdb_port: Option<NonZeroU16>,
     pub vfio_devices: Vec<VfioDevice>,
     pub dtbo: Option<File>,
-    pub device_tree_overlay: Option<File>,
+    pub reference_dt: Option<File>,
 }
 
 /// A disk image to pass to crosvm for a VM.
@@ -896,8 +896,10 @@
         .arg("--socket")
         .arg(add_preserved_fd(&mut preserved_fds, &control_server_socket.as_raw_descriptor()));
 
-    if let Some(dt_overlay) = &config.device_tree_overlay {
-        command.arg("--device-tree-overlay").arg(add_preserved_fd(&mut preserved_fds, dt_overlay));
+    if let Some(reference_dt) = &config.reference_dt {
+        command
+            .arg("--device-tree-overlay")
+            .arg(add_preserved_fd(&mut preserved_fds, reference_dt));
     }
 
     append_platform_devices(&mut command, &mut preserved_fds, &config)?;
diff --git a/virtualizationmanager/src/dt_overlay.rs b/virtualizationmanager/src/dt_overlay.rs
deleted file mode 100644
index c2d3c07..0000000
--- a/virtualizationmanager/src/dt_overlay.rs
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2024, The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//! This module support creating AFV related overlays, that can then be appended to DT by VM.
-
-use anyhow::{anyhow, Result};
-use cstr::cstr;
-use fsfdt::FsFdt;
-use libfdt::Fdt;
-use std::ffi::CStr;
-use std::path::Path;
-
-pub(crate) const AVF_NODE_NAME: &CStr = cstr!("avf");
-pub(crate) const UNTRUSTED_NODE_NAME: &CStr = cstr!("untrusted");
-pub(crate) const VM_REFERENCE_DT_ON_HOST_PATH: &str = "/proc/device-tree/avf/reference";
-pub(crate) const VM_DT_OVERLAY_PATH: &str = "vm_dt_overlay.dtbo";
-pub(crate) const VM_DT_OVERLAY_MAX_SIZE: usize = 2000;
-
-/// Provide ways to modify the device tree.
-#[derive(PartialEq, Eq)]
-pub(crate) enum DtAddition<'a> {
-    /// Include the device tree at given path.
-    FromPath(&'a Path),
-    /// Include a property in /avf/untrusted node. This node is used to specify host provided
-    /// properties such as `instance-id`.
-    /// pVM firmware does minimal validation of properties in this node.
-    AvfUntrustedProp(&'a CStr, &'a [u8]),
-}
-
-/// Given a list of `dt_additions`, return a Device tree overlay containing those!
-/// Example: with `create_device_tree_overlay(_, DtAddition::AvfUntrustedProp("instance-id", _))`
-/// ```
-///   {
-///     fragment@0 {
-///         target-path = "/";
-///         __overlay__ {
-///             avf {
-///                 untrusted { instance-id = [0x01 0x23 .. ] }
-///               }
-///             };
-///         };
-///     };
-/// };
-/// ```
-pub(crate) fn create_device_tree_overlay<'a>(
-    buffer: &'a mut [u8],
-    dt_additions: &[DtAddition],
-) -> Result<&'a mut Fdt> {
-    if dt_additions.is_empty() {
-        return Err(anyhow!("Expected non empty list of device tree additions"));
-    }
-
-    let (additional_properties, additional_paths): (Vec<_>, _) =
-        dt_additions.iter().partition(|o| matches!(o, DtAddition::AvfUntrustedProp(_, _)));
-
-    let fdt =
-        Fdt::create_empty_tree(buffer).map_err(|e| anyhow!("Failed to create empty Fdt: {e:?}"))?;
-    let mut root = fdt.root_mut().map_err(|e| anyhow!("Failed to get root: {e:?}"))?;
-    let mut node =
-        root.add_subnode(cstr!("fragment@0")).map_err(|e| anyhow!("Failed to fragment: {e:?}"))?;
-    node.setprop(cstr!("target-path"), b"/\0")
-        .map_err(|e| anyhow!("Failed to set target-path: {e:?}"))?;
-    let mut node = node
-        .add_subnode(cstr!("__overlay__"))
-        .map_err(|e| anyhow!("Failed to __overlay__ node: {e:?}"))?;
-
-    if !additional_properties.is_empty() {
-        let mut node = node
-            .add_subnode(AVF_NODE_NAME)
-            .map_err(|e| anyhow!("Failed to add avf node: {e:?}"))?;
-        let mut node = node
-            .add_subnode(UNTRUSTED_NODE_NAME)
-            .map_err(|e| anyhow!("Failed to add /avf/untrusted node: {e:?}"))?;
-        for prop in additional_properties {
-            if let DtAddition::AvfUntrustedProp(name, value) = prop {
-                node.setprop(name, value).map_err(|e| anyhow!("Failed to set property: {e:?}"))?;
-            }
-        }
-    }
-
-    for path in additional_paths {
-        if let DtAddition::FromPath(path) = path {
-            fdt.append(cstr!("/fragment@0/__overlay__"), path)?;
-        }
-    }
-    fdt.pack().map_err(|e| anyhow!("Failed to pack DT overlay, {e:?}"))?;
-
-    Ok(fdt)
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn empty_overlays_not_allowed() {
-        let mut buffer = vec![0_u8; VM_DT_OVERLAY_MAX_SIZE];
-        let res = create_device_tree_overlay(&mut buffer, &[]);
-        assert!(res.is_err());
-    }
-
-    #[test]
-    fn untrusted_prop_test() {
-        let mut buffer = vec![0_u8; VM_DT_OVERLAY_MAX_SIZE];
-        let prop_name = cstr!("XOXO");
-        let prop_val_input = b"OXOX";
-        let fdt = create_device_tree_overlay(
-            &mut buffer,
-            &[DtAddition::AvfUntrustedProp(prop_name, prop_val_input)],
-        )
-        .unwrap();
-
-        let prop_value_dt = fdt
-            .node(cstr!("/fragment@0/__overlay__/avf/untrusted"))
-            .unwrap()
-            .expect("/avf/untrusted node doesn't exist")
-            .getprop(prop_name)
-            .unwrap()
-            .expect("Prop not found!");
-        assert_eq!(prop_value_dt, prop_val_input, "Unexpected property value");
-    }
-}
diff --git a/virtualizationmanager/src/main.rs b/virtualizationmanager/src/main.rs
index b2a734a..2e542c3 100644
--- a/virtualizationmanager/src/main.rs
+++ b/virtualizationmanager/src/main.rs
@@ -19,8 +19,8 @@
 mod composite;
 mod crosvm;
 mod debug_config;
-mod dt_overlay;
 mod payload;
+mod reference_dt;
 mod selinux;
 
 use crate::aidl::{GLOBAL_SERVICE, VirtualizationService};
diff --git a/virtualizationmanager/src/reference_dt.rs b/virtualizationmanager/src/reference_dt.rs
new file mode 100644
index 0000000..797ee3c
--- /dev/null
+++ b/virtualizationmanager/src/reference_dt.rs
@@ -0,0 +1,93 @@
+// Copyright 2024, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Functions for VM reference DT
+
+use anyhow::{anyhow, Result};
+use cstr::cstr;
+use fsfdt::FsFdt;
+use libfdt::Fdt;
+use std::fs;
+use std::fs::File;
+use std::path::Path;
+
+const VM_REFERENCE_DT_ON_HOST_PATH: &str = "/proc/device-tree/avf/reference";
+const VM_REFERENCE_DT_NAME: &str = "vm_reference_dt.dtbo";
+const VM_REFERENCE_DT_MAX_SIZE: usize = 2000;
+
+// Parses to VM reference if exists.
+// TODO(b/318431695): Allow to parse from custom VM reference DT
+pub(crate) fn parse_reference_dt(out_dir: &Path) -> Result<Option<File>> {
+    parse_reference_dt_internal(
+        Path::new(VM_REFERENCE_DT_ON_HOST_PATH),
+        &out_dir.join(VM_REFERENCE_DT_NAME),
+    )
+}
+
+fn parse_reference_dt_internal(dir_path: &Path, fdt_path: &Path) -> Result<Option<File>> {
+    if !dir_path.exists() || fs::read_dir(dir_path)?.next().is_none() {
+        return Ok(None);
+    }
+
+    let mut data = vec![0_u8; VM_REFERENCE_DT_MAX_SIZE];
+
+    let fdt = Fdt::create_empty_tree(&mut data)
+        .map_err(|e| anyhow!("Failed to create an empty DT, {e:?}"))?;
+    let mut root = fdt.root_mut().map_err(|e| anyhow!("Failed to find the DT root, {e:?}"))?;
+    let mut fragment = root
+        .add_subnode(cstr!("fragment@0"))
+        .map_err(|e| anyhow!("Failed to create the fragment@0, {e:?}"))?;
+    fragment
+        .setprop(cstr!("target-path"), b"/\0")
+        .map_err(|e| anyhow!("Failed to set target-path, {e:?}"))?;
+    fragment
+        .add_subnode(cstr!("__overlay__"))
+        .map_err(|e| anyhow!("Failed to create the __overlay__, {e:?}"))?;
+
+    fdt.append(cstr!("/fragment@0/__overlay__"), dir_path)?;
+
+    fdt.pack().map_err(|e| anyhow!("Failed to pack VM reference DT, {e:?}"))?;
+    fs::write(fdt_path, fdt.as_slice())?;
+
+    Ok(Some(File::open(fdt_path)?))
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_parse_reference_dt_from_empty_dir() {
+        let empty_dir = tempfile::TempDir::new().unwrap();
+        let test_dir = tempfile::TempDir::new().unwrap();
+
+        let empty_dir_path = empty_dir.path();
+        let fdt_path = test_dir.path().join("test.dtb");
+
+        let fdt_file = parse_reference_dt_internal(empty_dir_path, &fdt_path).unwrap();
+
+        assert!(fdt_file.is_none());
+    }
+
+    #[test]
+    fn test_parse_reference_dt_from_empty_reference() {
+        let fdt_file = parse_reference_dt_internal(
+            Path::new("/this/path/would/not/exists"),
+            Path::new("test.dtb"),
+        )
+        .unwrap();
+
+        assert!(fdt_file.is_none());
+    }
+}