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 for Android: free password hash cracker in your pocket
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20240913112643.542914-3-benno.lossin@proton.me>
Date: Fri, 13 Sep 2024 11:27:01 +0000
From: Benno Lossin <benno.lossin@...ton.me>
To: Greg KH <gregkh@...uxfoundation.org>, 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>, Andreas Hindborg <a.hindborg@...sung.com>, Alice Ryhl <aliceryhl@...gle.com>, Trevor Gross <tmgross@...ch.edu>
Cc: rust-for-linux@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [RFC PATCH 2/3] WIP: rust: fs: mark data returned by inodes untrusted

This is only meant to show how one would use the untrusted data API, not
to be actually used in production, as I just added `Untrusted` where I
thought it might fit. I have no idea if this is actually the correct
place where the untrusted data path starts.
---
 rust/kernel/fs/inode.rs | 33 +++++++++++++++++++++------------
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/rust/kernel/fs/inode.rs b/rust/kernel/fs/inode.rs
index b2b7d000080e..349f7f1ab420 100644
--- a/rust/kernel/fs/inode.rs
+++ b/rust/kernel/fs/inode.rs
@@ -11,7 +11,9 @@
     PageOffset, UnspecifiedFS,
 };
 use crate::error::{code::*, from_err_ptr, Result};
-use crate::types::{ARef, AlwaysRefCounted, Either, ForeignOwnable, Lockable, Locked, Opaque};
+use crate::types::{
+    ARef, AlwaysRefCounted, Either, ForeignOwnable, Lockable, Locked, Opaque, Untrusted,
+};
 use crate::{
     bindings, block, build_error, container_of, folio, folio::Folio, mem_cache::MemCache,
     str::CStr, str::CString, time::Timespec,
@@ -133,21 +135,24 @@ pub unsafe fn mapper(&self) -> Mapper<T> {
     pub unsafe fn mapped_folio(
         &self,
         offset: Offset,
-    ) -> Result<folio::Mapped<'_, folio::PageCache<T>>> {
+    ) -> Result<Untrusted<folio::Mapped<'_, folio::PageCache<T>>>> {
         let page_index = offset >> bindings::PAGE_SHIFT;
         let page_offset = offset & ((bindings::PAGE_SIZE - 1) as Offset);
         let folio = self.read_mapping_folio(page_index.try_into()?)?;
+        let folio = folio.into_inner_untrusted();
 
         // SAFETY: The safety requirements guarantee that there are no concurrent mutable mappings
         // of the folio.
-        unsafe { Folio::map_owned(folio, page_offset.try_into()?) }
+        Ok(Untrusted::new_untrusted(unsafe {
+            Folio::map_owned(folio, page_offset.try_into()?)?
+        }))
     }
 
     /// Returns the folio at the given page index.
     pub fn read_mapping_folio(
         &self,
         index: PageOffset,
-    ) -> Result<ARef<Folio<folio::PageCache<T>>>> {
+    ) -> Result<Untrusted<ARef<Folio<folio::PageCache<T>>>>> {
         let folio = from_err_ptr(unsafe {
             bindings::read_mapping_folio(
                 (*self.0.get()).i_mapping,
@@ -159,7 +164,7 @@ pub fn read_mapping_folio(
             .ok_or(EIO)?
             .cast::<Folio<folio::PageCache<T>>>();
         // SAFETY: The folio returned by read_mapping_folio has had its refcount incremented.
-        Ok(unsafe { ARef::from_raw(ptr) })
+        Ok(Untrusted::new_untrusted(unsafe { ARef::from_raw(ptr) }))
     }
 
     /// Iterate over the given range, one folio at a time.
@@ -171,7 +176,7 @@ pub unsafe fn for_each_page<U>(
         &self,
         first: Offset,
         len: Offset,
-        mut cb: impl FnMut(&[u8]) -> Result<Option<U>>,
+        mut cb: impl FnMut(&Untrusted<[u8]>) -> Result<Option<U>>,
     ) -> Result<Option<U>> {
         if first >= self.size() {
             return Ok(None);
@@ -183,8 +188,9 @@ pub unsafe fn for_each_page<U>(
         while remain > 0 {
             // SAFETY: The safety requirements of this function satisfy those of `mapped_folio`.
             let data = unsafe { self.mapped_folio(next)? };
+            let data = data.into_inner_untrusted();
             let avail = cmp::min(data.len(), remain.try_into().unwrap_or(usize::MAX));
-            let ret = cb(&data[..avail])?;
+            let ret = cb(Untrusted::new_untrusted_ref(&data[..avail]))?;
             if ret.is_some() {
                 return Ok(ret);
             }
@@ -297,7 +303,7 @@ impl<T: FileSystem + ?Sized, U: Deref<Target = INode<T>>> Locked<U, ReadSem> {
     pub fn mapped_folio<'a>(
         &'a self,
         offset: Offset,
-    ) -> Result<folio::Mapped<'a, folio::PageCache<T>>>
+    ) -> Result<Untrusted<folio::Mapped<'a, folio::PageCache<T>>>>
     where
         T: 'a,
     {
@@ -315,7 +321,7 @@ pub fn for_each_page<V>(
         &self,
         first: Offset,
         len: Offset,
-        cb: impl FnMut(&[u8]) -> Result<Option<V>>,
+        cb: impl FnMut(&Untrusted<[u8]>) -> Result<Option<V>>,
     ) -> Result<Option<V>> {
         if T::IS_UNSPECIFIED {
             build_error!("unspecified file systems cannot safely map folios");
@@ -750,14 +756,17 @@ pub fn split_at(mut self, offset: Offset) -> (Self, Self) {
     }
 
     /// Returns a mapped folio at the given offset.
-    pub fn mapped_folio(&self, offset: Offset) -> Result<folio::Mapped<'_, folio::PageCache<T>>> {
+    pub fn mapped_folio(
+        &self,
+        offset: Offset,
+    ) -> Result<Untrusted<folio::Mapped<'_, folio::PageCache<T>>>> {
         if offset < self.begin || offset >= self.end {
             return Err(ERANGE);
         }
 
         // SAFETY: By the type invariant, there are no other mutable mappings of the folio.
         let mut map = unsafe { self.inode.mapped_folio(offset) }?;
-        map.cap_len((self.end - offset).try_into()?);
+        map.untrusted_mut().cap_len((self.end - offset).try_into()?);
         Ok(map)
     }
 
@@ -766,7 +775,7 @@ pub fn for_each_page<U>(
         &self,
         first: Offset,
         len: Offset,
-        cb: impl FnMut(&[u8]) -> Result<Option<U>>,
+        cb: impl FnMut(&Untrusted<[u8]>) -> Result<Option<U>>,
     ) -> Result<Option<U>> {
         if first < self.begin || first >= self.end {
             return Err(ERANGE);
-- 
2.46.0



Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ