1 | use crate::*; |
2 | use std::fs::copy; |
3 | use std::path::PathBuf; |
4 | use std::process::Command; |
5 | use tempfile::{tempdir, TempDir}; |
6 | |
7 | fn 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 | |
35 | use nix::errno::Errno; |
36 | use nix::kmod::{delete_module, DeleteModuleFlags}; |
37 | use nix::kmod::{finit_module, init_module, ModuleInitFlags}; |
38 | use std::ffi::CString; |
39 | use std::fs::File; |
40 | use std::io::Read; |
41 | |
42 | #[test] |
43 | fn 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] |
62 | fn 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] |
88 | fn 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] |
110 | fn 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] |
135 | fn 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] |
150 | fn 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] |
177 | fn 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 | |