Rust for Linux List
 help / color / mirror / Atom feed
From: Greg KH <gregkh@linuxfoundation.org>
To: Benno Lossin <lossin@kernel.org>
Cc: "Simona Vetter" <simona.vetter@ffwll.ch>,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Alex Gaynor" <alex.gaynor@gmail.com>,
	"Boqun Feng" <boqun.feng@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Danilo Krummrich" <dakr@kernel.org>,
	rust-for-linux@vger.kernel.org
Subject: Re: [PATCH v4 0/4] Untrusted Data API
Date: Sun, 17 Aug 2025 08:00:09 +0200	[thread overview]
Message-ID: <2025081746-aspirate-diminish-29cd@gregkh> (raw)
In-Reply-To: <DC3S011XG6ZJ.2LLG9DCOKD0Z5@kernel.org>

On Sat, Aug 16, 2025 at 12:22:04PM +0200, Benno Lossin wrote:
> On Fri Aug 15, 2025 at 4:19 PM CEST, Greg KH wrote:
> > On Fri, Aug 15, 2025 at 09:28:59AM +0200, Benno Lossin wrote:
> >> On Thu Aug 14, 2025 at 8:26 PM CEST, Greg KH wrote:
> >> > On Thu, Aug 14, 2025 at 07:23:45PM +0200, Benno Lossin wrote:
> >> >> On Thu Aug 14, 2025 at 5:42 PM CEST, Greg KH wrote:
> >> >> > On Thu, Aug 14, 2025 at 05:22:57PM +0200, Benno Lossin wrote:
> >> >> >> On Thu Aug 14, 2025 at 4:37 PM CEST, Greg KH wrote:
> >> >> >> > On Thu, Aug 14, 2025 at 02:44:12PM +0200, Benno Lossin wrote:
> >> >> >> >> I didn't have too much time to spend on this API, so this is mostly a
> >> >> >> >> resend of v3. There are some changes in the last commit, updating to the
> >> >> >> >> latest version of Alice's iov_iter patche series [1] & rebasing on top
> >> >> >> >> of v6.17-rc1.
> >> >> >> >> 
> >> >> >> >> I think we should just merge the first two patches this cycle in order
> >> >> >> >> to get the initial, bare-bones API into the kernel and have people
> >> >> >> >> experiment with it. The validation logic in the third patch still needs
> >> >> >> >> some work and I'd need to find some time to work on that (no idea when I
> >> >> >> >> find it though).
> >> >> >> >
> >> >> >> > Nice, thanks for reviving this!
> >> >> >> >
> >> >> >> > And we should at least add an example using it, otherwise it's not going
> >> >> >> > to help out much here.  Add it to the misc device driver api?
> >> >> >> 
> >> >> >> You mean `rust/kernel/miscdevice.rs`? What parts of that API are
> >> >> >> untrusted? 
> >> >> >
> >> >> > mmap() is, but you can't do anything about that...
> >> >> 
> >> >> Which parameter is untrusted there and why can't I do anything about it?
> >> >
> >> > The whole memory range is untrusted as to what is written there, sorry,
> >> > it was a bad attempt at a joke, the kernel never gets a chance to know
> >> > what is happening.
> >> 
> >> Ahh that flew over my head :) So we'd either build `Untrusted` directly
> >> into the `VmaNew`/`VmaRef` abstractions -- or if there is a way to have
> >> a trusted `VmaNew`, we can wrap it in `mmap`.
> >
> > Nah, I wouldn't worry about that, mmap() doesn't seem to cause security
> > issues as by definition it is just allowing userspace to read/write
> > anything to that device or memory, and the kernel doesn't even see it.
> > Because of that, the kernel can't really be "broken" with invalid data
> > there (hardware can, of course, but that's userspace's fault the kernel
> > is just setting up a pipe here.)
> 
> I'm guessing that the kernel doesn't usually read these? (if we don't
> have a way to read them from the Rust side, we don't need `Untrusted`)

Correct.

> >> >> If so we probably
> >> >> should have a single parameter so users can verify them at the same
> >> >> time. Or am I thinking of the wrong thing to verify? (`file` should be
> >> >> already in kernel memory, right?)
> >> >
> >> > Both are usually verified at different places, first `cmd` tells what
> >> > `arg` is going to be, and then the code goes off and parses whatever
> >> > `arg` points to (or contains for simple ioctls).
> >> >
> >> > And for some, `arg` is just a place to write something back, so `arg`
> >> > needs no verification for them, it depends on what `cmd` is.
> >> 
> >> I still think grouping them together makes sense, since in the
> >> validation function you'd want access to both, right? And these use
> >> cases seem perfect for enums:
> >> 
> >>     enum MyIoctlArgs {
> >>         WriteFoo(UserPtr<Foo>),
> >>         VerifyBar(UserPtr<Bar>),
> >>         // ...
> >>     }
> >> 
> >> And then in the validation function you can do:
> >> 
> >>     const WRITE_FOO_CMD: u32 = ...;
> >> 
> >>     fn validate(cmd: u32, arg: usize) -> Result<MyIoctlArgs> {
> >>         Ok(match cmd {
> >>             WRITE_FOO_CMD => MyIoctlArgs::WriteFoo(UserPtr::from_addr(arg)),
> >>             VERIFY_BAR_CMD => MyIoctlArgs::VerifyBar(UserPtr::from_addr(arg)),
> >>             _ => return Err(EINVAL),
> >>         })
> >>     }
> >> 
> >> So when wrapping them together we could have:
> >> 
> >>     pub struct IoctlArgs {
> >>         pub cmd: u32,
> >>         pub arg: usize,
> >>     }
> >> 
> >> And then change the `MiscDevice::ioctl` function to:
> >> 
> >>     fn ioctl(
> >>         _device: <Self::Ptr as ForeignOwnable>::Borrowed<'_>,
> >>         _file: &File,
> >>         _args: Untrusted<IoctlArgs>,
> >>     ) -> Result<isize>
> >
> > I think the problem with this is you now end up with the "I verified
> > this is ok, so now I will copy it" bug, where userspace will race with
> > the kernel and modify the data after verification but before copying.
> >
> > Note, Windows is full of these types of bugs as they don't do a call to
> > copy_from_user(), but usually just poke at the data directly.  Linux at
> > least forces a copy_from_user() call, but it doesn't always work in that
> > you still have to validate the data is correct and people forget.
> >
> > So as long as we can copy the data from userspace first, and then
> > validate it, and keep that validated copy around to use, that's great.
> > I can't really determine above if that is the case or not, sorry.
> 
> So if I understand the current API correctly, the `arg` and `cmd`
> parameters are copied from userspace (or rather they are direct
> parameters of the syscall), so you can't have the copy-after-validation
> bug there. Then in the `ioctl` function one currently just looks at
> `cmd` & then decides what to do with `arg`, possibly doing a
> `copy_from_user`.
> 
> In my suggestion for the API, we just change the first part of the
> current approach, combining the two parameters to `ioctl` into a single
> struct & making people parse it using the untrusted API.
> 
> The API that protects you from the copy-after-validation bug is the
> `UserPtr<T>` abstraction. And there I also will add the untrusted API.
> For example the `UserPtr::read_all` function would become:
> 
>     pub fn read_all<A: Allocator>(self, buf: &mut Untrusted<Vec<u8, A>>, flags: Flags) -> Result;
> 
> This means that you can only read the data into an `Untrusted<Vec<u8>>`
> which ensures that the data is validated before use. This API also makes
> it harder to have the copy-after-validation bug, since you have to
> explicitly call `clone_reader`.

Ok, that sounds good!

  reply	other threads:[~2025-08-17  6:00 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-14 12:44 [PATCH v4 0/4] Untrusted Data API Benno Lossin
2025-08-14 12:44 ` [PATCH v4 1/4] rust: transmute: add `cast_slice[_mut]` functions Benno Lossin
2025-08-14 12:44 ` [PATCH v4 2/4] rust: create basic untrusted data API Benno Lossin
2025-08-29  5:23   ` Dirk Behme
2025-08-14 12:44 ` [RFC PATCH v4 3/4] rust: validate: add `Validate` trait Benno Lossin
2025-09-04  6:48   ` Dirk Behme
2025-08-14 12:44 ` [RFC PATCH v4 4/4] rust: iov: use untrusted data API Benno Lossin
2025-08-14 14:37 ` [PATCH v4 0/4] Untrusted Data API Greg KH
2025-08-14 15:22   ` Benno Lossin
2025-08-14 15:42     ` Greg KH
2025-08-14 17:23       ` Benno Lossin
2025-08-14 18:26         ` Greg KH
2025-08-15  7:28           ` Benno Lossin
2025-08-15 14:19             ` Greg KH
2025-08-16 10:22               ` Benno Lossin
2025-08-17  6:00                 ` Greg KH [this message]
2026-05-16 13:21 ` Greg KH

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2025081746-aspirate-diminish-29cd@gregkh \
    --to=gregkh@linuxfoundation.org \
    --cc=a.hindborg@kernel.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=dakr@kernel.org \
    --cc=gary@garyguo.net \
    --cc=lossin@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=simona.vetter@ffwll.ch \
    --cc=tmgross@umich.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox