diff --git a/src/cmdline.rs b/src/cmdline.rs index 4bcc01b..ab5a2e9 100644 --- a/src/cmdline.rs +++ b/src/cmdline.rs @@ -14,6 +14,7 @@ pub struct CmdlineOptions { pub nfsroot: Option, pub init: String, pub cleanup: bool, + pub bind_mount: Vec, } const SBIN_INIT: &str = "/sbin/init"; @@ -28,6 +29,7 @@ impl Default for CmdlineOptions { nfsroot: None, init: SBIN_INIT.into(), cleanup: true, + bind_mount: Vec::new(), } } } @@ -45,6 +47,9 @@ fn parse_option(key: &str, value: Option<&str>, options: &mut CmdlineOptions) -> "rw" => options.rootfsflags.remove(MsFlags::MS_RDONLY), "nfsroot" => options.nfsroot = Some(ensure_value(key, value)?.to_string()), "init" => options.init = ensure_value(key, value)?.into(), + "rsinit.bind" => options + .bind_mount + .push(ensure_value(key, value)?.to_string()), _ => (), } Ok(()) @@ -236,4 +241,19 @@ mod tests { assert_eq!(options, expected); } + + #[test] + fn test_rsinit_bind() { + let cmdline = "root=/dev/root rsinit.bind=/lib/modules rsinit.bind=/usr/lib/modules\n"; + + let expected = CmdlineOptions { + root: Some("/dev/root".into()), + bind_mount: vec!["/lib/modules".into(), "/usr/lib/modules".into()], + ..Default::default() + }; + + let options = parse_cmdline(cmdline).expect("failed"); + + assert_eq!(options, expected); + } } diff --git a/src/main.rs b/src/main.rs index c53d6e5..df67e40 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,6 +30,8 @@ use systemd::{mount_systemd, shutdown}; #[cfg(feature = "usb9pfs")] use usbg_9pfs::prepare_9pfs_gadget; +use crate::mount::mount_binds; + mod cmdline; #[cfg(feature = "dmverity")] mod dmverity; @@ -96,6 +98,7 @@ fn start_root(options: &mut CmdlineOptions) -> Result<()> { unlink(exe.as_path())?; } + mount_binds(options)?; mount_move_special(options)?; chdir("/root")?; diff --git a/src/mount.rs b/src/mount.rs index 2ea00b4..ff83199 100644 --- a/src/mount.rs +++ b/src/mount.rs @@ -4,7 +4,7 @@ use std::fs::remove_dir; use std::path::Path; -use log::debug; +use log::{debug, error}; use nix::mount::{mount, MsFlags}; use crate::cmdline::CmdlineOptions; @@ -105,3 +105,20 @@ pub fn mount_move_special(options: &CmdlineOptions) -> Result<()> { mount_move("/proc", "/root/proc", options.cleanup)?; Ok(()) } + +pub fn mount_binds(options: &CmdlineOptions) -> Result<()> { + for src in &options.bind_mount { + if !Path::new(src).exists() { + error!("Can't bind mount {} as it doesn't exist", src); + continue; + } + + let dst = format!("/root{src}"); + + debug!("Bind mounting {src} to {dst}"); + + do_mount(Some(src), &dst, None, MsFlags::MS_BIND, None)?; + } + + Ok(()) +}