KVM-based microVMM for the Volt platform: - Sub-second VM boot times - Minimal memory footprint - Landlock LSM + seccomp security - Virtio device support - Custom kernel management Copyright (c) Armored Gates LLC. All rights reserved. Licensed under AGPSL v5.0
110 lines
3.1 KiB
Rust
110 lines
3.1 KiB
Rust
// System utilities: signal handling, hostname, kernel cmdline, console
|
|
|
|
use std::ffi::CString;
|
|
|
|
/// Set up console I/O by ensuring fd 0/1/2 point to /dev/console or /dev/ttyS0
|
|
pub fn setup_console() {
|
|
// Try /dev/console first, then /dev/ttyS0
|
|
let consoles = ["/dev/console", "/dev/ttyS0"];
|
|
|
|
for console in &consoles {
|
|
let c_path = CString::new(*console).unwrap();
|
|
let fd = unsafe { libc::open(c_path.as_ptr(), libc::O_RDWR | libc::O_NOCTTY | libc::O_NONBLOCK) };
|
|
if fd >= 0 {
|
|
// Clear O_NONBLOCK now that the open succeeded
|
|
unsafe {
|
|
let flags = libc::fcntl(fd, libc::F_GETFL);
|
|
if flags >= 0 {
|
|
libc::fcntl(fd, libc::F_SETFL, flags & !libc::O_NONBLOCK);
|
|
}
|
|
}
|
|
|
|
// Close existing fds and dup console to 0, 1, 2
|
|
if fd != 0 {
|
|
unsafe {
|
|
libc::close(0);
|
|
libc::dup2(fd, 0);
|
|
}
|
|
}
|
|
unsafe {
|
|
libc::close(1);
|
|
libc::dup2(fd, 1);
|
|
libc::close(2);
|
|
libc::dup2(fd, 2);
|
|
}
|
|
if fd > 2 {
|
|
unsafe {
|
|
libc::close(fd);
|
|
}
|
|
}
|
|
|
|
// Make this our controlling terminal
|
|
unsafe {
|
|
libc::ioctl(0, libc::TIOCSCTTY as libc::Ioctl, 1);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
// If we get here, no console device available — output will be lost
|
|
}
|
|
|
|
/// Install signal handlers for PID 1
|
|
pub fn install_signal_handlers() {
|
|
unsafe {
|
|
// SIGCHLD: reap zombies
|
|
libc::signal(
|
|
libc::SIGCHLD,
|
|
sigchld_handler as *const () as libc::sighandler_t,
|
|
);
|
|
|
|
// SIGTERM: ignore (PID 1 handles shutdown via shell)
|
|
libc::signal(libc::SIGTERM, libc::SIG_IGN);
|
|
|
|
// SIGINT: ignore (Ctrl+C shouldn't kill init)
|
|
libc::signal(libc::SIGINT, libc::SIG_IGN);
|
|
}
|
|
}
|
|
|
|
extern "C" fn sigchld_handler(_sig: libc::c_int) {
|
|
// Reap all zombie children
|
|
unsafe {
|
|
loop {
|
|
let ret = libc::waitpid(-1, std::ptr::null_mut(), libc::WNOHANG);
|
|
if ret <= 0 {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Read kernel command line
|
|
pub fn read_kernel_cmdline() -> String {
|
|
std::fs::read_to_string("/proc/cmdline")
|
|
.unwrap_or_default()
|
|
.trim()
|
|
.to_string()
|
|
}
|
|
|
|
/// Parse a key=value from kernel cmdline
|
|
pub fn parse_cmdline_value(cmdline: &str, key: &str) -> Option<String> {
|
|
let prefix = format!("{}=", key);
|
|
for param in cmdline.split_whitespace() {
|
|
if let Some(value) = param.strip_prefix(&prefix) {
|
|
return Some(value.to_string());
|
|
}
|
|
}
|
|
None
|
|
}
|
|
|
|
/// Set system hostname
|
|
pub fn set_hostname(name: &str) {
|
|
let c_name = CString::new(name).unwrap();
|
|
let ret = unsafe { libc::sethostname(c_name.as_ptr(), name.len()) };
|
|
if ret != 0 {
|
|
eprintln!(
|
|
"[volt-init] Failed to set hostname: {}",
|
|
std::io::Error::last_os_error()
|
|
);
|
|
}
|
|
}
|