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