diff --git a/rust/helpers.c b/rust/helpers.c index f57f9340f49f3b..a6e98abb13efdf 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -10,6 +10,7 @@ #include #include #include +#include void rust_helper_BUG(void) { @@ -183,6 +184,34 @@ void rust_helper_put_task_struct(struct task_struct * t) } EXPORT_SYMBOL_GPL(rust_helper_put_task_struct); +int rust_helper_security_binder_set_context_mgr(struct task_struct *mgr) +{ + return security_binder_set_context_mgr(mgr); +} +EXPORT_SYMBOL_GPL(rust_helper_security_binder_set_context_mgr); + +int rust_helper_security_binder_transaction(struct task_struct *from, + struct task_struct *to) +{ + return security_binder_transaction(from, to); +} +EXPORT_SYMBOL_GPL(rust_helper_security_binder_transaction); + +int rust_helper_security_binder_transfer_binder(struct task_struct *from, + struct task_struct *to) +{ + return security_binder_transfer_binder(from, to); +} +EXPORT_SYMBOL_GPL(rust_helper_security_binder_transfer_binder); + +int rust_helper_security_binder_transfer_file(struct task_struct *from, + struct task_struct *to, + struct file *file) +{ + return security_binder_transfer_file(from, to, file); +} +EXPORT_SYMBOL_GPL(rust_helper_security_binder_transfer_file); + /* We use bindgen's --size_t-is-usize option to bind the C size_t type * as the Rust usize type, so we can use it in contexts where Rust * expects a usize like slice (array) indices. usize is defined to be diff --git a/rust/kernel/bindings_helper.h b/rust/kernel/bindings_helper.h index 148c75a902bb62..c64a6307da37ec 100644 --- a/rust/kernel/bindings_helper.h +++ b/rust/kernel/bindings_helper.h @@ -17,6 +17,7 @@ #include #include #include +#include // `bindgen` gets confused at certain things const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL; diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 7201cebd7981df..dd7479c35e3e22 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -50,6 +50,7 @@ pub mod file; pub mod file_operations; pub mod miscdev; pub mod pages; +pub mod security; pub mod str; pub mod task; pub mod traits; diff --git a/rust/kernel/security.rs b/rust/kernel/security.rs new file mode 100644 index 00000000000000..c38b0dceb345aa --- /dev/null +++ b/rust/kernel/security.rs @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Linux Security Modules (LSM). +//! +//! C header: [`include/linux/security.h`](../../../../include/linux/security.h). + +use crate::{bindings, c_types, error::Error, file::File, task::Task, Result}; + +extern "C" { + #[allow(improper_ctypes)] + fn rust_helper_security_binder_set_context_mgr( + mgr: *mut bindings::task_struct, + ) -> c_types::c_int; + #[allow(improper_ctypes)] + fn rust_helper_security_binder_transaction( + from: *mut bindings::task_struct, + to: *mut bindings::task_struct, + ) -> c_types::c_int; + #[allow(improper_ctypes)] + fn rust_helper_security_binder_transfer_binder( + from: *mut bindings::task_struct, + to: *mut bindings::task_struct, + ) -> c_types::c_int; + #[allow(improper_ctypes)] + fn rust_helper_security_binder_transfer_file( + from: *mut bindings::task_struct, + to: *mut bindings::task_struct, + file: *mut bindings::file, + ) -> c_types::c_int; +} + +/// Calls the security modules to determine if the given task can become the manager of a binder +/// context. +pub fn binder_set_context_mgr(mgr: &Task) -> Result { + // SAFETY: By the `Task` invariants, `mgr.ptr` is valid. + let ret = unsafe { rust_helper_security_binder_set_context_mgr(mgr.ptr) }; + if ret != 0 { + Err(Error::from_kernel_errno(ret)) + } else { + Ok(()) + } +} + +/// Calls the security modules to determine if binder transactions are allowed from task `from` to +/// task `to`. +pub fn binder_transaction(from: &Task, to: &Task) -> Result { + // SAFETY: By the `Task` invariants, `from.ptr` and `to.ptr` are valid. + let ret = unsafe { rust_helper_security_binder_transaction(from.ptr, to.ptr) }; + if ret != 0 { + Err(Error::from_kernel_errno(ret)) + } else { + Ok(()) + } +} + +/// Calls the security modules to determine if task `from` is allowed to send binder objects +/// (owned by itself or other processes) to task `to` through a binder transaction. +pub fn binder_transfer_binder(from: &Task, to: &Task) -> Result { + // SAFETY: By the `Task` invariants, `from.ptr` and `to.ptr` are valid. + let ret = unsafe { rust_helper_security_binder_transfer_binder(from.ptr, to.ptr) }; + if ret != 0 { + Err(Error::from_kernel_errno(ret)) + } else { + Ok(()) + } +} + +/// Calls the security modules to determine if task `from` is allowed to send the given file to +/// task `to` (which would get its own file descriptor) through a binder transaction. +pub fn binder_transfer_file(from: &Task, to: &Task, file: &File) -> Result { + // SAFETY: By the `Task` invariants, `from.ptr` and `to.ptr` are valid. Similarly, by the + // `File` invariants, `file.ptr` is also valid. + let ret = unsafe { rust_helper_security_binder_transfer_file(from.ptr, to.ptr, file.ptr) }; + if ret != 0 { + Err(Error::from_kernel_errno(ret)) + } else { + Ok(()) + } +}