agent: Ignore already mounted dev/fs/pseudo-fs

Using an initrd and setting KATA_INIT=yes meaning we're using the kata-agent
as the init process we need to make sure that the agent is not segfaulting
if mounts are already happened. Some workloads need to configure several
things in the initrd before the kata-agent starts which involves having
/proc or /sys already mounted.

Fixes: #6992

Signed-off-by: Zvonko Kaiser <zkaiser@nvidia.com>
This commit is contained in:
Zvonko Kaiser 2023-05-30 15:38:54 +00:00
parent 58e921eace
commit 07810bf71f

View File

@ -145,6 +145,11 @@ pub const STORAGE_HANDLER_LIST: &[&str] = &[
DRIVER_WATCHABLE_BIND_TYPE,
];
#[instrument]
pub fn get_mounts() -> Result<String, std::io::Error> {
fs::read_to_string("/proc/mounts")
}
#[instrument]
pub fn baremount(
source: &Path,
@ -168,6 +173,31 @@ pub fn baremount(
return Err(anyhow!("need mount FS type"));
}
let destination_str = destination.to_string_lossy();
let mounts = get_mounts().unwrap_or_else(|_| String::new());
let already_mounted = mounts
.lines()
.map(|line| line.split_whitespace().collect::<Vec<&str>>())
.filter(|parts| parts.len() >= 3) // ensure we have at least [source}, destination, and fs_type
.any(|parts| {
// Check if source, destination and fs_type match any entry in /proc/mounts
// minimal check is for destination an fstype since source can have different names like:
// udev /dev devtmpfs
// dev /dev devtmpfs
// depending on which entity is mounting the dev/fs/pseudo-fs
parts[1] == destination_str && parts[2] == fs_type
});
if already_mounted {
slog_info!(
logger,
"{:?} is already mounted at {:?}",
source,
destination
);
return Ok(());
}
info!(
logger,
"baremount source={:?}, dest={:?}, fs_type={:?}, options={:?}, flags={:?}",
@ -1112,6 +1142,42 @@ mod tests {
skip_if_not_root, skip_loop_by_user, skip_loop_if_not_root, skip_loop_if_root,
};
// Shadow get_mounts during tests since this is only used in the test
// context, compiler will warn about dead-code.
#[allow(dead_code)]
fn get_mounts() -> Result<String, std::io::Error> {
Ok(String::from(
"
rootfs / rootfs rw,size=1694984k,nr_inodes=423746 0 0
proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
sys /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0
dev /dev devtmpfs rw,nosuid,relatime,size=1695000k,nr_inodes=423750,mode=755 0 0
run /run tmpfs rw,nosuid,nodev,relatime,mode=755 0 0
",
))
}
#[test]
fn test_already_baremounted() {
let drain = slog::Discard;
let logger = slog::Logger::root(drain, o!());
let test_cases = [
("dev", "/dev", "devtmpfs"),
("udev", "/dev", "devtmpfs"),
("proc", "/proc", "proc"),
("sysfs", "/sys", "sysfs"),
];
for &(source, destination, fs_type) in &test_cases {
let source = Path::new(source);
let destination = Path::new(destination);
let flags = MsFlags::MS_RDONLY;
let options = "mode=755";
println!("baremount({:?} {:?} {:?}", source, destination, fs_type);
assert!(baremount(source, destination, fs_type, flags, options, &logger).is_ok());
}
}
#[test]
fn test_mount() {
#[derive(Debug)]