Skip to content

Commit 732dae7

Browse files
committed
Add wrapper for linux kernel module loading
- init_module and finit_module to load kernel modules - delete_module to unload kernel modules
1 parent 237ec7b commit 732dae7

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed

src/kmod.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//! Load and unload kernel modules.
2+
3+
use libc;
4+
use std::ffi::CStr;
5+
use std::os::unix::io::AsRawFd;
6+
7+
use errno::Errno;
8+
use Result;
9+
10+
/// Loads an ELF image into kernel space, performs any necessary symbol relocations,
11+
/// initializes module parameters to values provided by the caller, and then runs the module's init function.
12+
/// This function requires privilege.
13+
///
14+
/// The module_image argument points to a buffer containing the binary image to be loaded.
15+
/// The module image should be a valid ELF image, built for the running kernel.
16+
///
17+
/// The param_values argument is a string containing space-delimited specifications of the values for module parameters.
18+
/// Each of the parameter specifications has the form:
19+
///
20+
/// `name[=value[,value...]]`
21+
///
22+
/// Example usage:
23+
///
24+
/// ```no_run
25+
/// use std::fs::File;
26+
/// use std::io::Read;
27+
/// use std::ffi::CString;
28+
/// use nix::kmod::init_module;
29+
///
30+
/// let mut f = File::open("mykernel.ko").unwrap();
31+
/// let mut contents: Vec<u8> = Vec::new();
32+
/// f.read_to_end(&mut contents).unwrap();
33+
/// init_module(&mut contents, &CString::new("").unwrap()).unwrap();
34+
/// ```
35+
///
36+
pub fn init_module(module_image: &[u8], param_values: &CStr) -> Result<()> {
37+
let res = unsafe {
38+
libc::syscall(
39+
libc::SYS_init_module,
40+
module_image.as_ptr(),
41+
module_image.len(),
42+
param_values.as_ptr(),
43+
)
44+
};
45+
46+
Errno::result(res).map(drop)
47+
}
48+
49+
libc_bitflags!(
50+
/// Flags used by the `finit_module` function.
51+
pub struct ModuleInitFlags: libc::c_uint {
52+
/// Ignore symbol version hashes.
53+
MODULE_INIT_IGNORE_MODVERSIONS;
54+
/// Ignore kernel version magic.
55+
MODULE_INIT_IGNORE_VERMAGIC;
56+
}
57+
);
58+
59+
/// Loads a kernel module from a given file descriptor.
60+
///
61+
/// Example usage:
62+
///
63+
/// ```no_run
64+
/// use std::fs::File;
65+
/// use std::ffi::CString;
66+
/// use nix::kmod::{finit_module, ModuleInitFlags};
67+
///
68+
/// let f = File::open("mymod.ko").unwrap();
69+
/// finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty()).unwrap();
70+
/// ```
71+
///
72+
pub fn finit_module<T: AsRawFd>(fd: &T, param_values: &CStr, flags: ModuleInitFlags) -> Result<()> {
73+
let res = unsafe {
74+
libc::syscall(
75+
libc::SYS_finit_module,
76+
fd.as_raw_fd(),
77+
param_values.as_ptr(),
78+
flags.bits(),
79+
)
80+
};
81+
82+
Errno::result(res).map(drop)
83+
}
84+
85+
libc_bitflags!(
86+
/// Flags used by `delete_module`.
87+
pub struct OFlags: libc::c_int {
88+
O_NONBLOCK;
89+
O_TRUNC;
90+
}
91+
);
92+
93+
/// Unloads the kernel module with the given name.
94+
///
95+
/// Example usage:
96+
///
97+
/// ```no_run
98+
/// use std::ffi::CString;
99+
/// use nix::kmod::{delete_module, OFlags};
100+
///
101+
/// delete_module(&CString::new("mymod").unwrap(), OFlags::O_NONBLOCK).unwrap();
102+
/// ```
103+
///
104+
pub fn delete_module(name: &CStr, flags: OFlags) -> Result<()> {
105+
let res = unsafe { libc::syscall(libc::SYS_delete_module, name.as_ptr(), flags.bits()) };
106+
107+
Errno::result(res).map(drop)
108+
}

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ pub mod fcntl;
4343
target_os = "openbsd"))]
4444
pub mod ifaddrs;
4545
#[cfg(any(target_os = "linux", target_os = "android"))]
46+
pub mod kmod;
47+
#[cfg(any(target_os = "linux", target_os = "android"))]
4648
pub mod mount;
4749
#[cfg(any(target_os = "dragonfly",
4850
target_os = "freebsd",

0 commit comments

Comments
 (0)