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