Skip to content

Commit

Permalink
fix: use pivot_root instead of chroot
Browse files Browse the repository at this point in the history
This commit fixes issues with `docker exec`. Changing the root with `chroot` does not actually change the root mount point but merely the way paths are resolved. This leads to issues with `docker exec` where the mount points are not set up correctly for the executed process. Using `pivot_root` instead resolves these issues.
  • Loading branch information
koehlma committed Apr 5, 2024
1 parent 81cd232 commit f929bff
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 28 deletions.
31 changes: 14 additions & 17 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ homepage = "https://oss.silitics.com/rugpi/"
anyhow = "1.0.71"
clap = { version = "4.3", features = ["derive"] }
serde = { version = "1", features = ["derive"] }
nix = { version = "0.28", features = ["ioctl", "fs", "mount", "process"] }
xscript = "0.3.0"
8 changes: 7 additions & 1 deletion crates/rugpi-common/src/partitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,13 @@ pub fn find_dev(path: impl AsRef<Path>) -> Anyhow<PathBuf> {
pub fn system_dev() -> Anyhow<&'static Path> {
static SYSTEM_DEV: OnceLock<Anyhow<PathBuf>> = OnceLock::new();
SYSTEM_DEV
.get_or_init(|| find_dev("/run/rugpi/mounts/system"))
.get_or_init(|| {
if Path::new(MOUNT_POINT_SYSTEM).exists() {
find_dev(MOUNT_POINT_SYSTEM)
} else {
find_dev("/")
}
})
.as_ref()
.map(AsRef::as_ref)
.map_err(|error| anyhow!("error retrieving system device: {error}"))
Expand Down
29 changes: 19 additions & 10 deletions crates/rugpi-ctrl/src/init.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use std::{ffi::CString, fs, io, path::Path, thread, time::Duration};

use anyhow::{bail, ensure};
use nix::mount::MntFlags;
use rugpi_common::{
ctrl_config::{load_config, Config, Overlay},
partitions::{
get_disk_id, get_hot_partitions, is_block_dev, mkfs_ext4, sfdisk_apply_layout,
sfdisk_system_layout, Partitions, MOUNT_POINT_CONFIG, MOUNT_POINT_DATA, MOUNT_POINT_SYSTEM,
sfdisk_system_layout, system_dev, Partitions, MOUNT_POINT_CONFIG, MOUNT_POINT_DATA,
MOUNT_POINT_SYSTEM,
},
patch_boot, Anyhow,
};
Expand Down Expand Up @@ -70,8 +72,9 @@ fn init() -> Anyhow<()> {
run!([MOUNT, "-o", "noatime", &partitions.data, MOUNT_POINT_DATA])?;

// 4️⃣ Setup remaining mount points in `/run/rugpi/mounts`.
let system_dev = system_dev()?;
fs::create_dir_all(MOUNT_POINT_SYSTEM).ok();
run!([MOUNT, "--bind", "/", MOUNT_POINT_SYSTEM])?;
run!([MOUNT, "-o", "ro", system_dev, MOUNT_POINT_SYSTEM])?;
fs::create_dir_all(MOUNT_POINT_CONFIG).ok();
run!([MOUNT, "-o", "ro", &partitions.config, MOUNT_POINT_CONFIG])?;

Expand Down Expand Up @@ -187,7 +190,7 @@ fn setup_root_overlay(
"overlay",
"overlay",
"-o",
"noatime,lowerdir=/,upperdir={hot_overlay_state},workdir={OVERLAY_WORK_DIR}",
"noatime,lowerdir={MOUNT_POINT_SYSTEM},upperdir={hot_overlay_state},workdir={OVERLAY_WORK_DIR}",
OVERLAY_ROOT_DIR
])?;
run!([MOUNT, "--rbind", "/run", overlay_root_dir().join("run")])?;
Expand Down Expand Up @@ -310,14 +313,20 @@ fn restore_machine_id() -> Anyhow<()> {
Ok(())
}

/// The `chroot` executable.
const CHROOT: &str = "/usr/sbin/chroot";

/// Changes the root directory and hands off to Systemd.
/// Changes the root directory and hands off to the system init process.
///
/// We follow the example from the manpage of the `pivot_root` system call here.
///
/// We are not using `chroot` as this lead to problems with Docker.
fn exec_chroot_init() -> Anyhow<()> {
let chroot_prog = &CString::new(CHROOT).unwrap();
let new_root = &CString::new(OVERLAY_ROOT_DIR).unwrap();
println!("Changing current working directory to overlay root directory.");
nix::unistd::chdir(OVERLAY_ROOT_DIR)?;
println!("Pivoting root mount point to current working directory.");
nix::unistd::pivot_root(".", ".")?;
println!("Unmounting the previous root filesystem.");
nix::mount::umount2(".", MntFlags::MNT_DETACH)?;
println!("Starting system init process.");
let systemd_init = &CString::new("/sbin/init").unwrap();
nix::unistd::execv(chroot_prog, &[chroot_prog, new_root, systemd_init])?;
nix::unistd::execv(systemd_init, &[systemd_init])?;
Ok(())
}
2 changes: 2 additions & 0 deletions rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[toolchain]
targets = [ "aarch64-unknown-linux-musl", "arm-unknown-linux-musleabihf" ]

0 comments on commit f929bff

Please sign in to comment.