Remove CAP_IPC_LOCK from crosvm, use CAP_SYS_RESOURCE on VS
Crosvm currently has a capability that allows it to mlock() unlimited
amounts of RAM, necessary for running protected VMs. This mechanims is
not compatible with switching to crosvm as a child process, so replace
it with setrlimit from virtualizationservice. The limit is set to
RLIM_INFINITY to preserve the original property.
Bug: 204298056
Bug: 245727626
Test: atest MicrodroidTestApp
Change-Id: Iec393f5c0548f7eac1ba162214b57350d8328637
diff --git a/apex/canned_fs_config b/apex/canned_fs_config
index 1cf63b6..ce942d3 100644
--- a/apex/canned_fs_config
+++ b/apex/canned_fs_config
@@ -1 +1 @@
-/bin/crosvm 0 2000 0755 capabilities=0x4000
+/bin/virtualizationservice 0 2000 0755 capabilities=0x1000000 # CAP_SYS_RESOURCE
diff --git a/virtualizationservice/src/main.rs b/virtualizationservice/src/main.rs
index cea2747..714bcfd 100644
--- a/virtualizationservice/src/main.rs
+++ b/virtualizationservice/src/main.rs
@@ -24,8 +24,8 @@
use crate::aidl::{VirtualizationService, BINDER_SERVICE_IDENTIFIER, TEMPORARY_DIRECTORY};
use android_logger::{Config, FilterBuilder};
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::IVirtualizationService::BnVirtualizationService;
+use anyhow::{bail, Context, Error};
use binder::{register_lazy_service, BinderFeatures, ProcessState};
-use anyhow::Error;
use log::{info, Level};
use std::fs::{remove_dir_all, remove_file, read_dir};
@@ -44,6 +44,7 @@
),
);
+ remove_memlock_rlimit().expect("Failed to remove memlock rlimit");
clear_temporary_files().expect("Failed to delete old temporary files");
let service = VirtualizationService::init();
@@ -53,6 +54,18 @@
ProcessState::join_thread_pool();
}
+/// Set this PID's RLIMIT_MEMLOCK to RLIM_INFINITY to allow crosvm (a child process) to mlock()
+/// arbitrary amounts of memory. This is necessary for spawning protected VMs.
+fn remove_memlock_rlimit() -> Result<(), Error> {
+ let lim = libc::rlimit { rlim_cur: libc::RLIM_INFINITY, rlim_max: libc::RLIM_INFINITY };
+ // SAFETY - borrowing the new limit struct only
+ match unsafe { libc::setrlimit(libc::RLIMIT_MEMLOCK, &lim) } {
+ 0 => Ok(()),
+ -1 => Err(std::io::Error::last_os_error()).context("setrlimit failed"),
+ n => bail!("Unexpected return value from setrlimit(): {}", n),
+ }
+}
+
/// Remove any files under `TEMPORARY_DIRECTORY`.
fn clear_temporary_files() -> Result<(), Error> {
for dir_entry in read_dir(TEMPORARY_DIRECTORY)? {