-
Notifications
You must be signed in to change notification settings - Fork 308
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Refactor init into test-distro
The init module contains a small init system for running our integration tests against a kernel. While we don't need a full-blown linux distro, we do need some utilities. Once such utility is `modprobe` which allows us to load kernel modules. Rather than create a new module for this utility, I've instead refactored `init` into `test-distro` which is a module that contains multiple binaries. The xtask code has been adjusted to ensure these binaries are inserted into the correct places in our cpio archive, as well as bringing in the kernel modules. Signed-off-by: Dave Tucker <[email protected]>
- Loading branch information
1 parent
921e457
commit bc64c61
Showing
9 changed files
with
231 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
[package] | ||
name = "test-distro" | ||
version = "0.1.0" | ||
publish = false | ||
authors.workspace = true | ||
license.workspace = true | ||
repository.workspace = true | ||
homepage.workspace = true | ||
edition.workspace = true | ||
|
||
[[bin]] | ||
name = "init" | ||
path = "src/init.rs" | ||
|
||
[[bin]] | ||
name = "modprobe" | ||
path = "src/modprobe.rs" | ||
|
||
[dependencies] | ||
anyhow = { workspace = true, features = ["std"] } | ||
clap = { workspace = true, default-features = true, features = ["derive"] } | ||
nix = { workspace = true, features = ["fs", "mount", "reboot", "kmod"] } | ||
glob = { workspace = true } | ||
xz2 = { workspace = true } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
//! modprobe is used to load kernel modules into the kernel. | ||
//! | ||
//! This implementation is incredibly naive and is only designed to work within | ||
//! the constraints of the test environment. Not for production use. | ||
use std::{ffi::CString, io::Read as _}; | ||
|
||
use clap::Parser; | ||
use glob::glob; | ||
use nix::kmod::init_module; | ||
|
||
#[derive(Parser)] | ||
struct Args { | ||
/// Suppress all output | ||
#[clap(short, long, default_value = "false")] | ||
quiet: bool, | ||
|
||
/// Provide the path to the modules directory for testing | ||
#[clap(long, default_value = "/lib/modules")] | ||
modules_dir: String, | ||
name: String, | ||
} | ||
|
||
fn main() { | ||
let args = Args::parse(); | ||
|
||
// This modprobe only loads modules. | ||
// It also doesn't handle dependencies. | ||
|
||
let module = &args.name; | ||
let pattern = format!("{}/**/{}.k*", args.modules_dir, module); | ||
|
||
let matches = glob(&pattern) | ||
.expect("Failed to read glob pattern") | ||
.filter_map(Result::ok) | ||
.collect::<Vec<_>>(); | ||
|
||
if matches.is_empty() { | ||
if !args.quiet { | ||
eprintln!("No module found for pattern: {}", pattern); | ||
} | ||
std::process::exit(1); | ||
} | ||
|
||
let path = &matches[0]; | ||
|
||
if !args.quiet { | ||
println!("Loading module: {}", path.display()); | ||
} | ||
let mut f = std::fs::File::open(path).expect("Failed to open module file"); | ||
let mut contents: Vec<u8> = Vec::new(); | ||
f.read_to_end(&mut contents).unwrap(); | ||
|
||
if let Some(extension) = path.extension() { | ||
if extension == "xz" { | ||
if !args.quiet { | ||
println!("Decompressing module"); | ||
} | ||
let mut decompressed = Vec::new(); | ||
xz2::read::XzDecoder::new(&contents[..]) | ||
.read_to_end(&mut decompressed) | ||
.expect("Failed to decompress module"); | ||
contents = decompressed; | ||
} | ||
} | ||
|
||
if contents[0..4] != [0x7f, 0x45, 0x4c, 0x46] { | ||
if !args.quiet { | ||
eprintln!("Module is not an valid ELF file"); | ||
} | ||
std::process::exit(1); | ||
} | ||
|
||
init_module(&contents, &CString::new("").unwrap()).expect("Failed to load module into kernel"); | ||
|
||
if !args.quiet { | ||
println!("Module loaded successfully"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ mod info; | |
mod iter; | ||
mod load; | ||
mod log; | ||
mod modprobe; | ||
mod raw_tracepoint; | ||
mod rbpf; | ||
mod relocations; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
use std::{path::Path, process::Command}; | ||
|
||
use aya::programs::tc; | ||
|
||
use crate::utils::NetNsGuard; | ||
|
||
// FIXME: Delete this test before merging. | ||
// This is used to test the modprobe command inside the vm. | ||
#[test] | ||
fn modprobe() { | ||
println!("PATH: {:?}", std::env::var("PATH").unwrap()); | ||
|
||
// check modprobe exists | ||
assert!(Path::new("/sbin/modprobe").exists()); | ||
|
||
// This operation requires the kernel to load | ||
// the sch_ingress module. If module auto-loading | ||
// is working correctly, this should succeed... | ||
// However, I haven't cracked that nut yet, so for now... | ||
let _ = Command::new("modprobe") | ||
.arg("sch_ingress") | ||
.status() | ||
.expect("failed to execute modprobe"); | ||
|
||
let _netns = NetNsGuard::new(); | ||
|
||
tc::qdisc_add_clsact("lo").unwrap(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters