diff --git a/hello-world/src/lib.rs b/hello-world/src/lib.rs index 3473f7fa..33d0b84d 100644 --- a/hello-world/src/lib.rs +++ b/hello-world/src/lib.rs @@ -30,7 +30,7 @@ impl Drop for HelloWorldModule { linux_kernel_module::kernel_module!( HelloWorldModule, - author: "Fish in a Barrel Contributors", - description: "An extremely simple kernel module", - license: "GPL" + author: b"Fish in a Barrel Contributors", + description: b"An extremely simple kernel module", + license: b"GPL" ); diff --git a/src/lib.rs b/src/lib.rs index e0ee4ccd..4cd21081 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,9 +36,9 @@ pub use crate::types::{CStr, Mode}; /// /// linux_kernel_module::kernel_module!( /// MyKernelModule, -/// author: "Fish in a Barrel Contributors", -/// description: "My very own kernel module!", -/// license: "GPL" +/// author: b"Fish in a Barrel Contributors", +/// description: b"My very own kernel module!", +/// license: b"GPL" /// ); #[macro_export] macro_rules! kernel_module { @@ -72,13 +72,43 @@ macro_rules! kernel_module { )* }; - (@attribute $name:ident, $value:expr) => { + // TODO: The modinfo attributes below depend on the compiler placing + // the variables in order in the .modinfo section, so that you end up + // with b"key=value\0" in order in the section. This is a reasonably + // standard trick in C, but I'm not sure that rustc guarantees it. + // + // Ideally we'd be able to use concat_bytes! + stringify_bytes! + + // some way of turning a string literal (or at least a string + // literal token) into a bytes literal, and get a single static + // [u8; * N] with the whole thing, but those don't really exist yet. + // Most of the alternatives (e.g. .as_bytes() as a const fn) give + // you a pointer, not an array, which isn't right. + + (@attribute author, $value:expr) => { + #[link_section = ".modinfo"] + pub static AUTHOR_KEY: [u8; 7] = *b"author="; + #[link_section = ".modinfo"] + pub static AUTHOR_VALUE: [u8; $value.len()] = *$value; + #[link_section = ".modinfo"] + pub static AUTHOR_NUL: [u8; 1] = *b"\0"; + }; + + (@attribute description, $value:expr) => { + #[link_section = ".modinfo"] + pub static DESCRIPTION_KEY: [u8; 12] = *b"description="; + #[link_section = ".modinfo"] + pub static DESCRIPTION_VALUE: [u8; $value.len()] = *$value; + #[link_section = ".modinfo"] + pub static DESCRIPTION_NUL: [u8; 1] = *b"\0"; + }; + + (@attribute license, $value:expr) => { + #[link_section = ".modinfo"] + pub static LICENSE_KEY: [u8; 8] = *b"license="; + #[link_section = ".modinfo"] + pub static LICENSE_VALUE: [u8; $value.len()] = *$value; #[link_section = ".modinfo"] - #[allow(non_upper_case_globals)] - // TODO: Generate a name the same way the kernel's `__MODULE_INFO` does. - // TODO: This needs to be a `[u8; _]`, since the kernel defines this as a `const char []`. - // See https://github.com/rust-lang/rfcs/pull/2545 - pub static $name: &'static [u8] = concat!(stringify!($name), "=", $value, '\0').as_bytes(); + pub static LICENSE_NUL: [u8; 1] = *b"\0"; }; } diff --git a/tests/chrdev-region-allocation/src/lib.rs b/tests/chrdev-region-allocation/src/lib.rs index 027ac02d..f84c7620 100644 --- a/tests/chrdev-region-allocation/src/lib.rs +++ b/tests/chrdev-region-allocation/src/lib.rs @@ -20,7 +20,7 @@ impl linux_kernel_module::KernelModule for ChrdevRegionAllocationTestModule { linux_kernel_module::kernel_module!( ChrdevRegionAllocationTestModule, - author: "Fish in a Barrel Contributors", - description: "A module for testing character device region allocation", - license: "GPL" + author: b"Fish in a Barrel Contributors", + description: b"A module for testing character device region allocation", + license: b"GPL" ); diff --git a/tests/chrdev/src/lib.rs b/tests/chrdev/src/lib.rs index 053694ac..047ee01b 100644 --- a/tests/chrdev/src/lib.rs +++ b/tests/chrdev/src/lib.rs @@ -124,7 +124,7 @@ impl linux_kernel_module::KernelModule for ChrdevTestModule { linux_kernel_module::kernel_module!( ChrdevTestModule, - author: "Fish in a Barrel Contributors", - description: "A module for testing character devices", - license: "GPL" + author: b"Fish in a Barrel Contributors", + description: b"A module for testing character devices", + license: b"GPL" ); diff --git a/tests/filesystem/src/lib.rs b/tests/filesystem/src/lib.rs index d9fa7128..0f939221 100644 --- a/tests/filesystem/src/lib.rs +++ b/tests/filesystem/src/lib.rs @@ -27,7 +27,7 @@ impl linux_kernel_module::KernelModule for TestFSModule { linux_kernel_module::kernel_module!( TestFSModule, - author: "Fish in a Barrel Contributors", - description: "A module for testing filesystem::register", - license: "GPL" + author: b"Fish in a Barrel Contributors", + description: b"A module for testing filesystem::register", + license: b"GPL" ); diff --git a/tests/modinfo/Cargo.toml b/tests/modinfo/Cargo.toml new file mode 100644 index 00000000..1a2a36a3 --- /dev/null +++ b/tests/modinfo/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "modinfo-tests" +version = "0.1.0" +authors = ["Alex Gaynor ", "Geoffrey Thomas "] +edition = "2018" + +[lib] +crate-type = ["staticlib"] +test = false + +[features] +default = ["linux-kernel-module"] + +[dependencies] +linux-kernel-module = { path = "../..", optional = true } + +[dev-dependencies] +kernel-module-testlib = { path = "../../testlib" } diff --git a/tests/modinfo/src/lib.rs b/tests/modinfo/src/lib.rs new file mode 100644 index 00000000..2208ae43 --- /dev/null +++ b/tests/modinfo/src/lib.rs @@ -0,0 +1,18 @@ +#![no_std] + +use linux_kernel_module; + +struct ModinfoTestModule; + +impl linux_kernel_module::KernelModule for ModinfoTestModule { + fn init() -> linux_kernel_module::KernelResult { + Ok(ModinfoTestModule) + } +} + +linux_kernel_module::kernel_module!( + ModinfoTestModule, + author: b"Fish in a Barrel Contributors", + description: b"Empty module for testing modinfo", + license: b"GPL" +); diff --git a/tests/modinfo/tests/tests.rs b/tests/modinfo/tests/tests.rs new file mode 100644 index 00000000..c45e65bb --- /dev/null +++ b/tests/modinfo/tests/tests.rs @@ -0,0 +1,38 @@ +use std::env; +use std::fs; +use std::path::Path; +use std::process::Command; + +use kernel_module_testlib::with_kernel_module; + +#[test] +fn test_modinfo() { + let module = env::var("KERNEL_MODULE").unwrap(); + + for (key, value) in &[ + ("author", "Fish in a Barrel Contributors"), + ("description", "Empty module for testing modinfo"), + ("license", "GPL"), + ] { + let modinfo = Command::new("modinfo") + .arg("-F") + .arg(key) + .arg(&module) + .output() + .unwrap(); + assert!(modinfo.status.success()); + assert_eq!(&std::str::from_utf8(&modinfo.stdout).unwrap().trim(), value); + } +} + +#[test] +fn test_no_proprietary_taint() { + let module = env::var("KERNEL_MODULE").unwrap(); + let module_name = Path::new(&module).file_stem().unwrap(); + let sysfs_path = Path::new("/sys/module").join(module_name).join("taint"); + + with_kernel_module(|| { + let taints = fs::read_to_string(&sysfs_path).unwrap(); + assert!(!taints.contains("P")); + }); +} diff --git a/tests/printk/src/lib.rs b/tests/printk/src/lib.rs index 049aade5..aafa307e 100644 --- a/tests/printk/src/lib.rs +++ b/tests/printk/src/lib.rs @@ -16,7 +16,7 @@ impl linux_kernel_module::KernelModule for PrintkTestModule { linux_kernel_module::kernel_module!( PrintkTestModule, - author: "Fish in a Barrel Contributors", - description: "A module for testing println!()", - license: "GPL" + author: b"Fish in a Barrel Contributors", + description: b"A module for testing println!()", + license: b"GPL" ); diff --git a/tests/random/src/lib.rs b/tests/random/src/lib.rs index ad33325b..070d1ca2 100644 --- a/tests/random/src/lib.rs +++ b/tests/random/src/lib.rs @@ -44,7 +44,7 @@ impl linux_kernel_module::KernelModule for RandomTestModule { linux_kernel_module::kernel_module!( RandomTestModule, - author: "Fish in a Barrel Contributors", - description: "A module for testing the CSPRNG", - license: "GPL" + author: b"Fish in a Barrel Contributors", + description: b"A module for testing the CSPRNG", + license: b"GPL" ); diff --git a/tests/run_tests.py b/tests/run_tests.py index f3a5c197..2da0129b 100755 --- a/tests/run_tests.py +++ b/tests/run_tests.py @@ -18,7 +18,7 @@ def run(*args, **kwargs): def main(argv): - for path in os.listdir(BASE_DIR): + for path in argv[1:] or os.listdir(BASE_DIR): if ( not os.path.isdir(os.path.join(BASE_DIR, path)) or not os.path.exists(os.path.join(BASE_DIR, path, "tests")) diff --git a/tests/sysctl-get/src/lib.rs b/tests/sysctl-get/src/lib.rs index 8aed402b..ea50ca65 100644 --- a/tests/sysctl-get/src/lib.rs +++ b/tests/sysctl-get/src/lib.rs @@ -38,7 +38,7 @@ impl Drop for SysctlGetTestModule { linux_kernel_module::kernel_module!( SysctlGetTestModule, - author: "Fish in a Barrel Contributors", - description: "A module for testing sysctls", - license: "GPL" + author: b"Fish in a Barrel Contributors", + description: b"A module for testing sysctls", + license: b"GPL" ); diff --git a/tests/sysctl/src/lib.rs b/tests/sysctl/src/lib.rs index 0b95b8dd..2d2788af 100644 --- a/tests/sysctl/src/lib.rs +++ b/tests/sysctl/src/lib.rs @@ -33,7 +33,7 @@ impl linux_kernel_module::KernelModule for SysctlTestModule { linux_kernel_module::kernel_module!( SysctlTestModule, - author: "Fish in a Barrel Contributors", - description: "A module for testing sysctls", - license: "GPL" + author: b"Fish in a Barrel Contributors", + description: b"A module for testing sysctls", + license: b"GPL" ); diff --git a/tests/utils/src/lib.rs b/tests/utils/src/lib.rs index 49daaf62..3db6ae9f 100644 --- a/tests/utils/src/lib.rs +++ b/tests/utils/src/lib.rs @@ -15,7 +15,7 @@ impl linux_kernel_module::KernelModule for UtilsTestModule { linux_kernel_module::kernel_module!( UtilsTestModule, - author: "Fish in a Barrel Contributors", - description: "A module for testing various utilities", - license: "GPL" + author: b"Fish in a Barrel Contributors", + description: b"A module for testing various utilities", + license: b"GPL" );