diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/kmod.rs | 123 | ||||
-rw-r--r-- | src/lib.rs | 9 | ||||
-rw-r--r-- | src/pty.rs | 3 |
3 files changed, 131 insertions, 4 deletions
diff --git a/src/kmod.rs b/src/kmod.rs new file mode 100644 index 00000000..e853261b --- /dev/null +++ b/src/kmod.rs @@ -0,0 +1,123 @@ +//! Load and unload kernel modules. +//! +//! For more details see + +use libc; +use std::ffi::CStr; +use std::os::unix::io::AsRawFd; + +use errno::Errno; +use Result; + +/// Loads a kernel module from a buffer. +/// +/// It loads an ELF image into kernel space, +/// performs any necessary symbol relocations, +/// initializes module parameters to values provided by the caller, +/// and then runs the module's init function. +/// +/// This function requires `CAP_SYS_MODULE` privilege. +/// +/// The `module_image` argument points to a buffer containing the binary image +/// to be loaded. The buffer should contain a valid ELF image +/// built for the running kernel. +/// +/// The `param_values` argument is a string containing space-delimited specifications +/// of the values for module parameters. +/// Each of the parameter specifications has the form: +/// +/// `name[=value[,value...]]` +/// +/// # Example +/// +/// ```no_run +/// use std::fs::File; +/// use std::io::Read; +/// use std::ffi::CString; +/// use nix::kmod::init_module; +/// +/// let mut f = File::open("mykernel.ko").unwrap(); +/// let mut contents: Vec<u8> = Vec::new(); +/// f.read_to_end(&mut contents).unwrap(); +/// init_module(&mut contents, &CString::new("who=Rust when=Now,12").unwrap()).unwrap(); +/// ``` +/// +/// See [`man init_module(2)`](http://man7.org/linux/man-pages/man2/init_module.2.html) for more information. +pub fn init_module(module_image: &[u8], param_values: &CStr) -> Result<()> { + let res = unsafe { + libc::syscall( + libc::SYS_init_module, + module_image.as_ptr(), + module_image.len(), + param_values.as_ptr(), + ) + }; + + Errno::result(res).map(drop) +} + +libc_bitflags!( + /// Flags used by the `finit_module` function. + pub struct ModuleInitFlags: libc::c_uint { + /// Ignore symbol version hashes. + MODULE_INIT_IGNORE_MODVERSIONS; + /// Ignore kernel version magic. + MODULE_INIT_IGNORE_VERMAGIC; + } +); + +/// Loads a kernel module from a given file descriptor. +/// +/// # Example +/// +/// ```no_run +/// use std::fs::File; +/// use std::ffi::CString; +/// use nix::kmod::{finit_module, ModuleInitFlags}; +/// +/// let f = File::open("mymod.ko").unwrap(); +/// finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty()).unwrap(); +/// ``` +/// +/// See [`man init_module(2)`](http://man7.org/linux/man-pages/man2/init_module.2.html) for more information. +pub fn finit_module<T: AsRawFd>(fd: &T, param_values: &CStr, flags: ModuleInitFlags) -> Result<()> { + let res = unsafe { + libc::syscall( + libc::SYS_finit_module, + fd.as_raw_fd(), + param_values.as_ptr(), + flags.bits(), + ) + }; + + Errno::result(res).map(drop) +} + +libc_bitflags!( + /// Flags used by `delete_module`. + /// + /// See [`man delete_module(2)`](http://man7.org/linux/man-pages/man2/delete_module.2.html) + /// for a detailed description how these flags work. + pub struct DeleteModuleFlags: libc::c_int { + O_NONBLOCK; + O_TRUNC; + } +); + +/// Unloads the kernel module with the given name. +/// +/// # Example +/// +/// ```no_run +/// use std::ffi::CString; +/// use nix::kmod::{delete_module, DeleteModuleFlags}; +/// +/// delete_module(&CString::new("mymod").unwrap(), DeleteModuleFlags::O_NONBLOCK).unwrap(); +/// ``` +/// +/// See [`man delete_module(2)`](http://man7.org/linux/man-pages/man2/delete_module.2.html) for more information. +pub fn delete_module(name: &CStr, flags: DeleteModuleFlags) -> Result<()> { + let res = unsafe { libc::syscall(libc::SYS_delete_module, name.as_ptr(), flags.bits()) }; + + Errno::result(res).map(drop) +} @@ -43,7 +43,11 @@ pub mod fcntl; target_os = "netbsd", target_os = "openbsd"))] pub mod ifaddrs; -#[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg(any(target_os = "android", + target_os = "linux"))] +pub mod kmod; +#[cfg(any(target_os = "android", + target_os = "linux"))] pub mod mount; #[cfg(any(target_os = "dragonfly", target_os = "freebsd", @@ -57,7 +61,8 @@ pub mod net; pub mod poll; #[deny(missing_docs)] pub mod pty; -#[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg(any(target_os = "android", + target_os = "linux"))] pub mod sched; pub mod sys; // This can be implemented for other platforms as soon as libc @@ -108,8 +108,7 @@ pub fn grantpt(fd: &PtyMaster) -> Result<()> { /// let slave_name = unsafe { ptsname(&master_fd) }?; /// /// // Try to open the slave -/// # #[allow(unused_variables)] -/// let slave_fd = open(Path::new(&slave_name), OFlag::O_RDWR, Mode::empty())?; +/// let _slave_fd = open(Path::new(&slave_name), OFlag::O_RDWR, Mode::empty())?; /// # Ok(()) /// # } /// ``` |