runtime-rs: hypervisor: add SELinux support functions

Implement core SELinux functionality including label parsing,
validation, and process label setting to support SELinux
enforcement on hypervisor processes.

Fixes #9866
Signed-off-by: Caspian443 <scrisis843@gmail.com>
This commit is contained in:
Caspian443
2025-07-22 16:20:28 +08:00
parent 1c718dbcdd
commit b8c5f648f0
2 changed files with 72 additions and 0 deletions

View File

@@ -18,6 +18,7 @@ pub mod dragonball;
pub mod firecracker;
mod kernel_param;
pub mod qemu;
pub mod selinux;
pub mod remote;
pub use kernel_param::Param;
pub mod utils;

View File

@@ -0,0 +1,71 @@
// Copyright 2024 The Kata Containers community
//
// SPDX-License-Identifier: Apache-2.0
use std::fs::{self, OpenOptions};
use std::io::prelude::*;
use std::path::Path;
use anyhow::{Context, Result};
use nix::unistd::gettid;
/// Check if SELinux is enabled on the system
pub fn is_selinux_enabled() -> bool {
let buf = match fs::read_to_string("/proc/mounts") {
Ok(content) => content,
Err(_) => return false,
};
buf.contains("selinuxfs")
}
pub fn set_exec_label(label: &str) -> Result<()> {
let mut attr_path = Path::new("/proc/thread-self/attr/exec").to_path_buf();
if !attr_path.exists() {
// Fall back to the old convention
attr_path = Path::new("/proc/self/task")
.join(gettid().to_string())
.join("attr/exec")
}
let mut file = OpenOptions::new()
.write(true)
.truncate(true)
.open(attr_path)?;
file.write_all(label.as_bytes())
.with_context(|| "failed to apply SELinux label")?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
const TEST_LABEL: &str = "system_u:system_r:unconfined_t:s0";
#[test]
fn test_is_selinux_enabled() {
let str = fs::read_to_string("/proc/mounts").unwrap();
let expected = str.contains("selinuxfs");
assert_eq!(is_selinux_enabled(), expected);
}
#[test]
fn test_set_exec_label() {
let ret = set_exec_label(TEST_LABEL);
if is_selinux_enabled() {
assert!(ret.is_ok(), "Expecting Ok, Got {:?}", ret);
// 检查 label 是否被正确设置
let mut attr_path = std::path::Path::new("/proc/thread-self/attr/exec").to_path_buf();
if !attr_path.exists() {
attr_path = std::path::Path::new("/proc/self/task")
.join(nix::unistd::gettid().to_string())
.join("attr/exec");
}
let label = std::fs::read_to_string(attr_path).unwrap();
assert_eq!(label.trim_end_matches('\0'), TEST_LABEL);
} else {
assert!(ret.is_err(), "Expecting error, Got {:?}", ret);
}
}
}