13da5c369Sopenharmony_ciuse crate::*;
23da5c369Sopenharmony_ciuse std::fs::copy;
33da5c369Sopenharmony_ciuse std::path::PathBuf;
43da5c369Sopenharmony_ciuse std::process::Command;
53da5c369Sopenharmony_ciuse tempfile::{tempdir, TempDir};
63da5c369Sopenharmony_ci
73da5c369Sopenharmony_cifn compile_kernel_module() -> (PathBuf, String, TempDir) {
83da5c369Sopenharmony_ci    let _m = crate::FORK_MTX.lock();
93da5c369Sopenharmony_ci
103da5c369Sopenharmony_ci    let tmp_dir =
113da5c369Sopenharmony_ci        tempdir().expect("unable to create temporary build directory");
123da5c369Sopenharmony_ci
133da5c369Sopenharmony_ci    copy(
143da5c369Sopenharmony_ci        "test/test_kmod/hello_mod/hello.c",
153da5c369Sopenharmony_ci        tmp_dir.path().join("hello.c"),
163da5c369Sopenharmony_ci    )
173da5c369Sopenharmony_ci    .expect("unable to copy hello.c to temporary build directory");
183da5c369Sopenharmony_ci    copy(
193da5c369Sopenharmony_ci        "test/test_kmod/hello_mod/Makefile",
203da5c369Sopenharmony_ci        tmp_dir.path().join("Makefile"),
213da5c369Sopenharmony_ci    )
223da5c369Sopenharmony_ci    .expect("unable to copy Makefile to temporary build directory");
233da5c369Sopenharmony_ci
243da5c369Sopenharmony_ci    let status = Command::new("make")
253da5c369Sopenharmony_ci        .current_dir(tmp_dir.path())
263da5c369Sopenharmony_ci        .status()
273da5c369Sopenharmony_ci        .expect("failed to run make");
283da5c369Sopenharmony_ci
293da5c369Sopenharmony_ci    assert!(status.success());
303da5c369Sopenharmony_ci
313da5c369Sopenharmony_ci    // Return the relative path of the build kernel module
323da5c369Sopenharmony_ci    (tmp_dir.path().join("hello.ko"), "hello".to_owned(), tmp_dir)
333da5c369Sopenharmony_ci}
343da5c369Sopenharmony_ci
353da5c369Sopenharmony_ciuse nix::errno::Errno;
363da5c369Sopenharmony_ciuse nix::kmod::{delete_module, DeleteModuleFlags};
373da5c369Sopenharmony_ciuse nix::kmod::{finit_module, init_module, ModuleInitFlags};
383da5c369Sopenharmony_ciuse std::ffi::CString;
393da5c369Sopenharmony_ciuse std::fs::File;
403da5c369Sopenharmony_ciuse std::io::Read;
413da5c369Sopenharmony_ci
423da5c369Sopenharmony_ci#[test]
433da5c369Sopenharmony_cifn test_finit_and_delete_module() {
443da5c369Sopenharmony_ci    require_capability!("test_finit_and_delete_module", CAP_SYS_MODULE);
453da5c369Sopenharmony_ci    let _m0 = crate::KMOD_MTX.lock();
463da5c369Sopenharmony_ci    let _m1 = crate::CWD_LOCK.read();
473da5c369Sopenharmony_ci
483da5c369Sopenharmony_ci    let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
493da5c369Sopenharmony_ci
503da5c369Sopenharmony_ci    let f = File::open(kmod_path).expect("unable to open kernel module");
513da5c369Sopenharmony_ci    finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty())
523da5c369Sopenharmony_ci        .expect("unable to load kernel module");
533da5c369Sopenharmony_ci
543da5c369Sopenharmony_ci    delete_module(
553da5c369Sopenharmony_ci        &CString::new(kmod_name).unwrap(),
563da5c369Sopenharmony_ci        DeleteModuleFlags::empty(),
573da5c369Sopenharmony_ci    )
583da5c369Sopenharmony_ci    .expect("unable to unload kernel module");
593da5c369Sopenharmony_ci}
603da5c369Sopenharmony_ci
613da5c369Sopenharmony_ci#[test]
623da5c369Sopenharmony_cifn test_finit_and_delete_module_with_params() {
633da5c369Sopenharmony_ci    require_capability!(
643da5c369Sopenharmony_ci        "test_finit_and_delete_module_with_params",
653da5c369Sopenharmony_ci        CAP_SYS_MODULE
663da5c369Sopenharmony_ci    );
673da5c369Sopenharmony_ci    let _m0 = crate::KMOD_MTX.lock();
683da5c369Sopenharmony_ci    let _m1 = crate::CWD_LOCK.read();
693da5c369Sopenharmony_ci
703da5c369Sopenharmony_ci    let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
713da5c369Sopenharmony_ci
723da5c369Sopenharmony_ci    let f = File::open(kmod_path).expect("unable to open kernel module");
733da5c369Sopenharmony_ci    finit_module(
743da5c369Sopenharmony_ci        &f,
753da5c369Sopenharmony_ci        &CString::new("who=Rust number=2018").unwrap(),
763da5c369Sopenharmony_ci        ModuleInitFlags::empty(),
773da5c369Sopenharmony_ci    )
783da5c369Sopenharmony_ci    .expect("unable to load kernel module");
793da5c369Sopenharmony_ci
803da5c369Sopenharmony_ci    delete_module(
813da5c369Sopenharmony_ci        &CString::new(kmod_name).unwrap(),
823da5c369Sopenharmony_ci        DeleteModuleFlags::empty(),
833da5c369Sopenharmony_ci    )
843da5c369Sopenharmony_ci    .expect("unable to unload kernel module");
853da5c369Sopenharmony_ci}
863da5c369Sopenharmony_ci
873da5c369Sopenharmony_ci#[test]
883da5c369Sopenharmony_cifn test_init_and_delete_module() {
893da5c369Sopenharmony_ci    require_capability!("test_init_and_delete_module", CAP_SYS_MODULE);
903da5c369Sopenharmony_ci    let _m0 = crate::KMOD_MTX.lock();
913da5c369Sopenharmony_ci    let _m1 = crate::CWD_LOCK.read();
923da5c369Sopenharmony_ci
933da5c369Sopenharmony_ci    let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
943da5c369Sopenharmony_ci
953da5c369Sopenharmony_ci    let mut f = File::open(kmod_path).expect("unable to open kernel module");
963da5c369Sopenharmony_ci    let mut contents: Vec<u8> = Vec::new();
973da5c369Sopenharmony_ci    f.read_to_end(&mut contents)
983da5c369Sopenharmony_ci        .expect("unable to read kernel module content to buffer");
993da5c369Sopenharmony_ci    init_module(&contents, &CString::new("").unwrap())
1003da5c369Sopenharmony_ci        .expect("unable to load kernel module");
1013da5c369Sopenharmony_ci
1023da5c369Sopenharmony_ci    delete_module(
1033da5c369Sopenharmony_ci        &CString::new(kmod_name).unwrap(),
1043da5c369Sopenharmony_ci        DeleteModuleFlags::empty(),
1053da5c369Sopenharmony_ci    )
1063da5c369Sopenharmony_ci    .expect("unable to unload kernel module");
1073da5c369Sopenharmony_ci}
1083da5c369Sopenharmony_ci
1093da5c369Sopenharmony_ci#[test]
1103da5c369Sopenharmony_cifn test_init_and_delete_module_with_params() {
1113da5c369Sopenharmony_ci    require_capability!(
1123da5c369Sopenharmony_ci        "test_init_and_delete_module_with_params",
1133da5c369Sopenharmony_ci        CAP_SYS_MODULE
1143da5c369Sopenharmony_ci    );
1153da5c369Sopenharmony_ci    let _m0 = crate::KMOD_MTX.lock();
1163da5c369Sopenharmony_ci    let _m1 = crate::CWD_LOCK.read();
1173da5c369Sopenharmony_ci
1183da5c369Sopenharmony_ci    let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
1193da5c369Sopenharmony_ci
1203da5c369Sopenharmony_ci    let mut f = File::open(kmod_path).expect("unable to open kernel module");
1213da5c369Sopenharmony_ci    let mut contents: Vec<u8> = Vec::new();
1223da5c369Sopenharmony_ci    f.read_to_end(&mut contents)
1233da5c369Sopenharmony_ci        .expect("unable to read kernel module content to buffer");
1243da5c369Sopenharmony_ci    init_module(&contents, &CString::new("who=Nix number=2015").unwrap())
1253da5c369Sopenharmony_ci        .expect("unable to load kernel module");
1263da5c369Sopenharmony_ci
1273da5c369Sopenharmony_ci    delete_module(
1283da5c369Sopenharmony_ci        &CString::new(kmod_name).unwrap(),
1293da5c369Sopenharmony_ci        DeleteModuleFlags::empty(),
1303da5c369Sopenharmony_ci    )
1313da5c369Sopenharmony_ci    .expect("unable to unload kernel module");
1323da5c369Sopenharmony_ci}
1333da5c369Sopenharmony_ci
1343da5c369Sopenharmony_ci#[test]
1353da5c369Sopenharmony_cifn test_finit_module_invalid() {
1363da5c369Sopenharmony_ci    require_capability!("test_finit_module_invalid", CAP_SYS_MODULE);
1373da5c369Sopenharmony_ci    let _m0 = crate::KMOD_MTX.lock();
1383da5c369Sopenharmony_ci    let _m1 = crate::CWD_LOCK.read();
1393da5c369Sopenharmony_ci
1403da5c369Sopenharmony_ci    let kmod_path = "/dev/zero";
1413da5c369Sopenharmony_ci
1423da5c369Sopenharmony_ci    let f = File::open(kmod_path).expect("unable to open kernel module");
1433da5c369Sopenharmony_ci    let result =
1443da5c369Sopenharmony_ci        finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty());
1453da5c369Sopenharmony_ci
1463da5c369Sopenharmony_ci    assert_eq!(result.unwrap_err(), Errno::EINVAL);
1473da5c369Sopenharmony_ci}
1483da5c369Sopenharmony_ci
1493da5c369Sopenharmony_ci#[test]
1503da5c369Sopenharmony_cifn test_finit_module_twice_and_delete_module() {
1513da5c369Sopenharmony_ci    require_capability!(
1523da5c369Sopenharmony_ci        "test_finit_module_twice_and_delete_module",
1533da5c369Sopenharmony_ci        CAP_SYS_MODULE
1543da5c369Sopenharmony_ci    );
1553da5c369Sopenharmony_ci    let _m0 = crate::KMOD_MTX.lock();
1563da5c369Sopenharmony_ci    let _m1 = crate::CWD_LOCK.read();
1573da5c369Sopenharmony_ci
1583da5c369Sopenharmony_ci    let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
1593da5c369Sopenharmony_ci
1603da5c369Sopenharmony_ci    let f = File::open(kmod_path).expect("unable to open kernel module");
1613da5c369Sopenharmony_ci    finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty())
1623da5c369Sopenharmony_ci        .expect("unable to load kernel module");
1633da5c369Sopenharmony_ci
1643da5c369Sopenharmony_ci    let result =
1653da5c369Sopenharmony_ci        finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty());
1663da5c369Sopenharmony_ci
1673da5c369Sopenharmony_ci    assert_eq!(result.unwrap_err(), Errno::EEXIST);
1683da5c369Sopenharmony_ci
1693da5c369Sopenharmony_ci    delete_module(
1703da5c369Sopenharmony_ci        &CString::new(kmod_name).unwrap(),
1713da5c369Sopenharmony_ci        DeleteModuleFlags::empty(),
1723da5c369Sopenharmony_ci    )
1733da5c369Sopenharmony_ci    .expect("unable to unload kernel module");
1743da5c369Sopenharmony_ci}
1753da5c369Sopenharmony_ci
1763da5c369Sopenharmony_ci#[test]
1773da5c369Sopenharmony_cifn test_delete_module_not_loaded() {
1783da5c369Sopenharmony_ci    require_capability!("test_delete_module_not_loaded", CAP_SYS_MODULE);
1793da5c369Sopenharmony_ci    let _m0 = crate::KMOD_MTX.lock();
1803da5c369Sopenharmony_ci    let _m1 = crate::CWD_LOCK.read();
1813da5c369Sopenharmony_ci
1823da5c369Sopenharmony_ci    let result = delete_module(
1833da5c369Sopenharmony_ci        &CString::new("hello").unwrap(),
1843da5c369Sopenharmony_ci        DeleteModuleFlags::empty(),
1853da5c369Sopenharmony_ci    );
1863da5c369Sopenharmony_ci
1873da5c369Sopenharmony_ci    assert_eq!(result.unwrap_err(), Errno::ENOENT);
1883da5c369Sopenharmony_ci}
189