Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .github/workflows/census.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,16 @@ jobs:
run: |
sudo apt-get install -qy --no-install-recommends busybox-static \
"$([ "$ROW" = A64 ] && echo qemu-system-arm || echo qemu-system-x86)"
target/release/rk boot --build "$OUT" --row "$ROW" --timeout 1500
# An i386 kernel cannot run the runner's own 64 bit busybox, so X32 gets the i386 one.
busybox=()
if [ "$ROW" = X32 ]; then
sudo dpkg --add-architecture i386
sudo apt-get update -q
(cd "$RUNNER_TEMP" && apt-get download busybox-static:i386 \
&& dpkg-deb -x busybox-static_*_i386.deb busybox-i386)
busybox=(--busybox "$RUNNER_TEMP/busybox-i386/bin/busybox")
fi
target/release/rk boot --build "$OUT" --row "$ROW" --timeout 1500 "${busybox[@]}"
env:
ROW: ${{ matrix.row }}
- name: keep the record
Expand Down
37 changes: 37 additions & 0 deletions crates/rk/src/boot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,24 @@ pub fn is_static_elf(bytes: &[u8]) -> bool {
})
}

/// Whether an ELF program runs on a kernel of that kbuild `ARCH`, read from its `e_machine` and its
/// class. An i386 kernel cannot start a 64 bit program, so a busybox taken from an amd64 runner
/// panics an X32 boot with "No working init found" before any check runs.
#[must_use]
pub fn runs_on(bytes: &[u8], arch: &str) -> bool {
if bytes.len() < 20 || &bytes[..4] != b"\x7fELF" {
return false;
}
let machine = u16::from_le_bytes([bytes[18], bytes[19]]);
match arch {
"x86_64" => machine == 62 || machine == 3,
"i386" => machine == 3 && bytes[4] == 1,
"arm64" => machine == 183,
"riscv" => machine == 243,
_ => true,
}
}

/// Everything `rk boot` was asked to do.
#[derive(Debug, Clone)]
pub struct Plan {
Expand Down Expand Up @@ -514,6 +532,25 @@ mod tests {
assert!(!is_static_elf(b"#!/bin/sh"));
}

#[test]
fn a_busybox_is_checked_against_the_row_it_boots() {
let mut elf = vec![0u8; 0x40];
elf[..4].copy_from_slice(b"\x7fELF");
elf[4] = 2;
elf[18] = 62;
assert!(runs_on(&elf, "x86_64"));
assert!(!runs_on(&elf, "i386"));
assert!(!runs_on(&elf, "arm64"));
elf[4] = 1;
elf[18] = 3;
assert!(runs_on(&elf, "i386"));
assert!(runs_on(&elf, "x86_64"));
elf[4] = 2;
elf[18] = 183;
assert!(runs_on(&elf, "arm64"));
assert!(!runs_on(b"#!/bin/sh", "x86_64"));
}

#[test]
fn the_console_is_read_for_markers_checks_and_panics() {
let mut o = Outcome::default();
Expand Down
13 changes: 12 additions & 1 deletion crates/rk/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -780,8 +780,19 @@ fn boot_command(repo: &Repo, args: &Args) -> Result<ExitCode, String> {
let initramfs = if let Some(path) = args.get("initramfs") {
std::path::PathBuf::from(path)
} else {
let busybox = read_busybox(args.get("busybox"))?;
if !boot::runs_on(&busybox, &row.arch) {
return Err(format!(
"{} is not a program the {} row's {} kernel can run; pass --busybox with one \
built for it",
args.get("busybox").unwrap_or("/bin/busybox"),
row.name,
row.arch
));
}
let path = build.join("initramfs.cpio");
write_initramfs(&path, args.get("busybox"))?;
std::fs::write(&path, boot::initramfs(&busybox))
.map_err(|e| format!("writing {}: {e}", path.display()))?;
path
};
let timeout = match args.get("timeout") {
Expand Down
Loading