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