1use crate::*; 2use std::fs::copy; 3use std::path::PathBuf; 4use std::process::Command; 5use tempfile::{tempdir, TempDir}; 6 7fn compile_kernel_module() -> (PathBuf, String, TempDir) { 8 let _m = crate::FORK_MTX.lock(); 9 10 let tmp_dir = 11 tempdir().expect("unable to create temporary build directory"); 12 13 copy( 14 "test/test_kmod/hello_mod/hello.c", 15 tmp_dir.path().join("hello.c"), 16 ) 17 .expect("unable to copy hello.c to temporary build directory"); 18 copy( 19 "test/test_kmod/hello_mod/Makefile", 20 tmp_dir.path().join("Makefile"), 21 ) 22 .expect("unable to copy Makefile to temporary build directory"); 23 24 let status = Command::new("make") 25 .current_dir(tmp_dir.path()) 26 .status() 27 .expect("failed to run make"); 28 29 assert!(status.success()); 30 31 // Return the relative path of the build kernel module 32 (tmp_dir.path().join("hello.ko"), "hello".to_owned(), tmp_dir) 33} 34 35use nix::errno::Errno; 36use nix::kmod::{delete_module, DeleteModuleFlags}; 37use nix::kmod::{finit_module, init_module, ModuleInitFlags}; 38use std::ffi::CString; 39use std::fs::File; 40use std::io::Read; 41 42#[test] 43fn test_finit_and_delete_module() { 44 require_capability!("test_finit_and_delete_module", CAP_SYS_MODULE); 45 let _m0 = crate::KMOD_MTX.lock(); 46 let _m1 = crate::CWD_LOCK.read(); 47 48 let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module(); 49 50 let f = File::open(kmod_path).expect("unable to open kernel module"); 51 finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty()) 52 .expect("unable to load kernel module"); 53 54 delete_module( 55 &CString::new(kmod_name).unwrap(), 56 DeleteModuleFlags::empty(), 57 ) 58 .expect("unable to unload kernel module"); 59} 60 61#[test] 62fn test_finit_and_delete_module_with_params() { 63 require_capability!( 64 "test_finit_and_delete_module_with_params", 65 CAP_SYS_MODULE 66 ); 67 let _m0 = crate::KMOD_MTX.lock(); 68 let _m1 = crate::CWD_LOCK.read(); 69 70 let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module(); 71 72 let f = File::open(kmod_path).expect("unable to open kernel module"); 73 finit_module( 74 &f, 75 &CString::new("who=Rust number=2018").unwrap(), 76 ModuleInitFlags::empty(), 77 ) 78 .expect("unable to load kernel module"); 79 80 delete_module( 81 &CString::new(kmod_name).unwrap(), 82 DeleteModuleFlags::empty(), 83 ) 84 .expect("unable to unload kernel module"); 85} 86 87#[test] 88fn test_init_and_delete_module() { 89 require_capability!("test_init_and_delete_module", CAP_SYS_MODULE); 90 let _m0 = crate::KMOD_MTX.lock(); 91 let _m1 = crate::CWD_LOCK.read(); 92 93 let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module(); 94 95 let mut f = File::open(kmod_path).expect("unable to open kernel module"); 96 let mut contents: Vec<u8> = Vec::new(); 97 f.read_to_end(&mut contents) 98 .expect("unable to read kernel module content to buffer"); 99 init_module(&contents, &CString::new("").unwrap()) 100 .expect("unable to load kernel module"); 101 102 delete_module( 103 &CString::new(kmod_name).unwrap(), 104 DeleteModuleFlags::empty(), 105 ) 106 .expect("unable to unload kernel module"); 107} 108 109#[test] 110fn test_init_and_delete_module_with_params() { 111 require_capability!( 112 "test_init_and_delete_module_with_params", 113 CAP_SYS_MODULE 114 ); 115 let _m0 = crate::KMOD_MTX.lock(); 116 let _m1 = crate::CWD_LOCK.read(); 117 118 let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module(); 119 120 let mut f = File::open(kmod_path).expect("unable to open kernel module"); 121 let mut contents: Vec<u8> = Vec::new(); 122 f.read_to_end(&mut contents) 123 .expect("unable to read kernel module content to buffer"); 124 init_module(&contents, &CString::new("who=Nix number=2015").unwrap()) 125 .expect("unable to load kernel module"); 126 127 delete_module( 128 &CString::new(kmod_name).unwrap(), 129 DeleteModuleFlags::empty(), 130 ) 131 .expect("unable to unload kernel module"); 132} 133 134#[test] 135fn test_finit_module_invalid() { 136 require_capability!("test_finit_module_invalid", CAP_SYS_MODULE); 137 let _m0 = crate::KMOD_MTX.lock(); 138 let _m1 = crate::CWD_LOCK.read(); 139 140 let kmod_path = "/dev/zero"; 141 142 let f = File::open(kmod_path).expect("unable to open kernel module"); 143 let result = 144 finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty()); 145 146 assert_eq!(result.unwrap_err(), Errno::EINVAL); 147} 148 149#[test] 150fn test_finit_module_twice_and_delete_module() { 151 require_capability!( 152 "test_finit_module_twice_and_delete_module", 153 CAP_SYS_MODULE 154 ); 155 let _m0 = crate::KMOD_MTX.lock(); 156 let _m1 = crate::CWD_LOCK.read(); 157 158 let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module(); 159 160 let f = File::open(kmod_path).expect("unable to open kernel module"); 161 finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty()) 162 .expect("unable to load kernel module"); 163 164 let result = 165 finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty()); 166 167 assert_eq!(result.unwrap_err(), Errno::EEXIST); 168 169 delete_module( 170 &CString::new(kmod_name).unwrap(), 171 DeleteModuleFlags::empty(), 172 ) 173 .expect("unable to unload kernel module"); 174} 175 176#[test] 177fn test_delete_module_not_loaded() { 178 require_capability!("test_delete_module_not_loaded", CAP_SYS_MODULE); 179 let _m0 = crate::KMOD_MTX.lock(); 180 let _m1 = crate::CWD_LOCK.read(); 181 182 let result = delete_module( 183 &CString::new("hello").unwrap(), 184 DeleteModuleFlags::empty(), 185 ); 186 187 assert_eq!(result.unwrap_err(), Errno::ENOENT); 188} 189