1 //! Load and unload kernel modules.
2 //!
3 //! For more details see
4 
5 use std::ffi::CStr;
6 use std::os::unix::io::{AsFd, AsRawFd};
7 
8 use crate::errno::Errno;
9 use crate::Result;
10 
11 /// Loads a kernel module from a buffer.
12 ///
13 /// It loads an ELF image into kernel space,
14 /// performs any necessary symbol relocations,
15 /// initializes module parameters to values provided by the caller,
16 /// and then runs the module's init function.
17 ///
18 /// This function requires `CAP_SYS_MODULE` privilege.
19 ///
20 /// The `module_image` argument points to a buffer containing the binary image
21 /// to be loaded. The buffer should contain a valid ELF image
22 /// built for the running kernel.
23 ///
24 /// The `param_values` argument is a string containing space-delimited specifications
25 /// of the values for module parameters.
26 /// Each of the parameter specifications has the form:
27 ///
28 /// `name[=value[,value...]]`
29 ///
30 /// # Example
31 ///
32 /// ```no_run
33 /// use std::fs::File;
34 /// use std::io::Read;
35 /// use std::ffi::CString;
36 /// use nix::kmod::init_module;
37 ///
38 /// let mut f = File::open("mykernel.ko").unwrap();
39 /// let mut contents: Vec<u8> = Vec::new();
40 /// f.read_to_end(&mut contents).unwrap();
41 /// init_module(&mut contents, &CString::new("who=Rust when=Now,12").unwrap()).unwrap();
42 /// ```
43 ///
44 /// See [`man init_module(2)`](https://man7.org/linux/man-pages/man2/init_module.2.html) for more information.
init_module(module_image: &[u8], param_values: &CStr) -> Result<()>45 pub fn init_module(module_image: &[u8], param_values: &CStr) -> Result<()> {
46     let res = unsafe {
47         libc::syscall(
48             libc::SYS_init_module,
49             module_image.as_ptr(),
50             module_image.len(),
51             param_values.as_ptr(),
52         )
53     };
54 
55     Errno::result(res).map(drop)
56 }
57 
58 libc_bitflags!(
59     /// Flags used by the `finit_module` function.
60     pub struct ModuleInitFlags: libc::c_uint {
61         /// Ignore symbol version hashes.
62         MODULE_INIT_IGNORE_MODVERSIONS;
63         /// Ignore kernel version magic.
64         MODULE_INIT_IGNORE_VERMAGIC;
65     }
66 );
67 
68 /// Loads a kernel module from a given file descriptor.
69 ///
70 /// # Example
71 ///
72 /// ```no_run
73 /// use std::fs::File;
74 /// use std::ffi::CString;
75 /// use nix::kmod::{finit_module, ModuleInitFlags};
76 ///
77 /// let f = File::open("mymod.ko").unwrap();
78 /// finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty()).unwrap();
79 /// ```
80 ///
81 /// See [`man init_module(2)`](https://man7.org/linux/man-pages/man2/init_module.2.html) for more information.
finit_module<Fd: AsFd>( fd: Fd, param_values: &CStr, flags: ModuleInitFlags, ) -> Result<()>82 pub fn finit_module<Fd: AsFd>(
83     fd: Fd,
84     param_values: &CStr,
85     flags: ModuleInitFlags,
86 ) -> Result<()> {
87     let res = unsafe {
88         libc::syscall(
89             libc::SYS_finit_module,
90             fd.as_fd().as_raw_fd(),
91             param_values.as_ptr(),
92             flags.bits(),
93         )
94     };
95 
96     Errno::result(res).map(drop)
97 }
98 
99 libc_bitflags!(
100     /// Flags used by `delete_module`.
101     ///
102     /// See [`man delete_module(2)`](https://man7.org/linux/man-pages/man2/delete_module.2.html)
103     /// for a detailed description how these flags work.
104     pub struct DeleteModuleFlags: libc::c_int {
105         /// `delete_module` will return immediately, with an error, if the module has a nonzero
106         /// reference count.
107         O_NONBLOCK;
108         /// `delete_module` will unload the module immediately, regardless of whether it has a
109         /// nonzero reference count.
110         O_TRUNC;
111     }
112 );
113 
114 /// Unloads the kernel module with the given name.
115 ///
116 /// # Example
117 ///
118 /// ```no_run
119 /// use std::ffi::CString;
120 /// use nix::kmod::{delete_module, DeleteModuleFlags};
121 ///
122 /// delete_module(&CString::new("mymod").unwrap(), DeleteModuleFlags::O_NONBLOCK).unwrap();
123 /// ```
124 ///
125 /// See [`man delete_module(2)`](https://man7.org/linux/man-pages/man2/delete_module.2.html) for more information.
delete_module(name: &CStr, flags: DeleteModuleFlags) -> Result<()>126 pub fn delete_module(name: &CStr, flags: DeleteModuleFlags) -> Result<()> {
127     let res = unsafe {
128         libc::syscall(libc::SYS_delete_module, name.as_ptr(), flags.bits())
129     };
130 
131     Errno::result(res).map(drop)
132 }
133