lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20230625121657.3631109-5-changxian.cqs@antgroup.com>
Date:   Sun, 25 Jun 2023 20:16:53 +0800
From:   "Qingsong Chen" <changxian.cqs@...group.com>
To:     linux-kernel@...r.kernel.org
Cc:     "田洪亮" <tate.thl@...group.com>,
        "Qingsong Chen" <changxian.cqs@...group.com>,
        "Miguel Ojeda" <ojeda@...nel.org>,
        "Alex Gaynor" <alex.gaynor@...il.com>,
        "Wedson Almeida Filho" <wedsonaf@...il.com>,
        "Boqun Feng" <boqun.feng@...il.com>, "Gary Guo" <gary@...yguo.net>,
        "Björn Roy Baron" <bjorn3_gh@...tonmail.com>,
        "Benno Lossin" <benno.lossin@...ton.me>,
        <rust-for-linux@...r.kernel.org>
Subject: [RFC PATCH 4/8] rust: kernel: add some info handler TargetOperations

- Add `status`/`message` to retrieve info of targets.
- Add `report_zones` to propagate report zones command
  to underlying devices.

Signed-off-by: Qingsong Chen <changxian.cqs@...group.com>
---
 rust/kernel/device_mapper.rs | 149 ++++++++++++++++++++++++++++++++++-
 1 file changed, 148 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/device_mapper.rs b/rust/kernel/device_mapper.rs
index aeda12245171..9a62208fda56 100644
--- a/rust/kernel/device_mapper.rs
+++ b/rust/kernel/device_mapper.rs
@@ -10,7 +10,7 @@
 
 use crate::error::to_result;
 use crate::prelude::*;
-use crate::str::CStr;
+use crate::str::{CStr, CString};
 use crate::types::Opaque;
 
 /// Declare operations that a device mapper target can do.
@@ -100,6 +100,24 @@ fn resume(t: &mut Target<Self>) {
     fn busy(t: &mut Target<Self>) -> bool {
         unimplemented!()
     }
+
+    /// Return the target status.
+    #[allow(unused)]
+    fn status(t: &mut Target<Self>, type_: StatusType, flags: StatusFlags) -> Option<CString> {
+        unimplemented!()
+    }
+
+    /// Handle messages to the target.
+    #[allow(unused)]
+    fn message(t: &mut Target<Self>, args: Args) -> Result<CString> {
+        unimplemented!()
+    }
+
+    /// Propagate report zones command to underlying devices.
+    #[allow(unused)]
+    fn report_zones(t: &mut Target<Self>, args: &mut [ReportZonesArgs]) -> Result {
+        unimplemented!()
+    }
 }
 
 /// Wrap the kernel struct `target_type`.
@@ -172,6 +190,9 @@ pub fn register<T: TargetOperations>(
                     (HAS_PRERESUME, preresume, dm_preresume_fn),
                     (HAS_RESUME, resume, dm_resume_fn),
                     (HAS_BUSY, busy, dm_busy_fn),
+                    (HAS_STATUS, status, dm_status_fn),
+                    (HAS_MESSAGE, message, dm_message_fn),
+                    (HAS_REPORT_ZONES, report_zones, dm_report_zones_fn),
                 );
 
                 to_result(bindings::dm_register_target(tt))
@@ -327,6 +348,69 @@ impl TargetType {
         let t = unsafe { Target::borrow_mut(ti) };
         T::busy(t) as _
     }
+    unsafe extern "C" fn dm_status_fn<T: TargetOperations>(
+        ti: *mut bindings::dm_target,
+        status_type: bindings::status_type_t,
+        status_flags: core::ffi::c_uint,
+        result: *mut core::ffi::c_char,
+        maxlen: core::ffi::c_uint,
+    ) {
+        // SAFETY: the kernel should pass valid `dm_target` pointer.
+        let t = unsafe { Target::borrow_mut(ti) };
+        if let Some(s) = T::status(t, status_type.into(), status_flags.into()) {
+            let count = s.len_with_nul().min(maxlen as _);
+            // SAFETY: the kernel should pass valid `result` pointer, and
+            // `count` is not greater than `maxlen`.
+            unsafe {
+                core::ptr::copy(s.as_char_ptr(), result, count);
+            }
+        }
+    }
+    unsafe extern "C" fn dm_message_fn<T: TargetOperations>(
+        ti: *mut bindings::dm_target,
+        argc: core::ffi::c_uint,
+        argv: *mut *mut core::ffi::c_char,
+        result: *mut core::ffi::c_char,
+        maxlen: core::ffi::c_uint,
+    ) -> core::ffi::c_int {
+        // SAFETY: the kernel splits arguments by `dm_split_args`, then pass
+        // suitable `argc` and `argv` to `dm_ctr_fn`. If `argc` is not zero,
+        // `argv` is non-null and valid.
+        let args = unsafe { Args::new(argc, argv) };
+
+        // SAFETY: the kernel should pass valid `dm_target` pointer.
+        let t = unsafe { Target::borrow_mut(ti) };
+        T::message(t, args).map_or_else(
+            |e| e.to_errno(),
+            // SAFETY: the kernel should pass valid `result` pointer, and
+            // `count` is not greater than `maxlen`.
+            |ret| unsafe {
+                let count = ret.len_with_nul().min(maxlen as _);
+                core::ptr::copy(ret.as_char_ptr(), result, count);
+                0
+            },
+        )
+    }
+    unsafe extern "C" fn dm_report_zones_fn<T: TargetOperations>(
+        ti: *mut bindings::dm_target,
+        args: *mut bindings::dm_report_zones_args,
+        nr_zones: core::ffi::c_uint,
+    ) -> core::ffi::c_int {
+        // SAFETY: the kernel should pass valid `dm_target` pointer.
+        let t = unsafe { Target::borrow_mut(ti) };
+
+        let args = if nr_zones > 0 {
+            // SAFETY: the kernel should pass valid `args`, if `nr_zones`
+            // is not zero.
+            unsafe {
+                let first = ReportZonesArgs::borrow_mut(args);
+                core::slice::from_raw_parts_mut(first as _, nr_zones as _)
+            }
+        } else {
+            &mut []
+        };
+        T::report_zones(t, args).map_or_else(|e| e.to_errno(), |_| 0)
+    }
 }
 
 /// Wrap the kernel struct `dm_target`.
@@ -511,6 +595,69 @@ unsafe fn borrow_mut<'a>(ptr: *mut bindings::map_info) -> &'a mut Self {
     }
 }
 
+/// Define target status types.
+#[repr(u32)]
+pub enum StatusType {
+    /// Request for some general info.
+    Info,
+
+    /// Request for more detailed info.
+    Table,
+
+    /// Request for some integrity info.
+    Ima,
+
+    /// Undefined.
+    Undefined,
+}
+
+impl From<u32> for StatusType {
+    fn from(value: u32) -> Self {
+        match value {
+            bindings::status_type_t_STATUSTYPE_INFO => Self::Info,
+            bindings::status_type_t_STATUSTYPE_TABLE => Self::Table,
+            bindings::status_type_t_STATUSTYPE_IMA => Self::Ima,
+            _ => Self::Undefined,
+        }
+    }
+}
+
+/// Define target status flags.
+#[repr(u32)]
+pub enum StatusFlags {
+    /// See `DM_STATUS_NOFLUSH_FLAG`.
+    NoFlush = 1 << 0,
+
+    /// Undefined.
+    Undefined,
+}
+
+impl From<u32> for StatusFlags {
+    fn from(value: u32) -> Self {
+        match value {
+            0 => Self::NoFlush,
+            _ => Self::Undefined,
+        }
+    }
+}
+
+/// Wrap the kernel struct `dm_report_zones_args`.
+pub struct ReportZonesArgs(Opaque<bindings::dm_report_zones_args>);
+
+impl ReportZonesArgs {
+    unsafe fn borrow_mut<'a>(ptr: *mut bindings::dm_report_zones_args) -> &'a mut Self {
+        // SAFETY: the caller should pass a valid `ptr`.
+        unsafe { &mut *(ptr as *mut Self) }
+    }
+
+    /// Return the next sector.
+    pub fn next_sector(&self) -> usize {
+        // SAFETY: `self.0` is borrowed form foreign pointer,
+        // should be valid.
+        unsafe { (*self.0.get()).next_sector as _ }
+    }
+}
+
 /// Wrap the `c_char` arguments, which yields `CStr`.
 pub struct Args {
     argc: core::ffi::c_uint,
-- 
2.40.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ