rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Danilo Krummrich <dakr@kernel.org>
To: Benno Lossin <benno.lossin@proton.me>
Cc: ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com,
	boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com,
	a.hindborg@samsung.com, aliceryhl@google.com,
	akpm@linux-foundation.org, daniel.almeida@collabora.com,
	faith.ekstrand@collabora.com, boris.brezillon@collabora.com,
	lina@asahilina.net, mcanal@igalia.com, zhiw@nvidia.com,
	acurrid@nvidia.com, cjia@nvidia.com, jhubbard@nvidia.com,
	airlied@redhat.com, ajanulgu@redhat.com, lyude@redhat.com,
	linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
	linux-mm@kvack.org
Subject: Re: [PATCH v4 04/28] rust: alloc: implement `Allocator` for `Kmalloc`
Date: Thu, 8 Aug 2024 11:42:20 +0200	[thread overview]
Message-ID: <ZrSS_N1R7zkiH_-E@pollux> (raw)
In-Reply-To: <d005fe7e-74a8-4609-92e0-5dd3743ca060@proton.me>

On Thu, Aug 08, 2024 at 08:55:29AM +0000, Benno Lossin wrote:
> On 08.08.24 01:05, Danilo Krummrich wrote:
> > On Wed, Aug 07, 2024 at 08:15:41PM +0000, Benno Lossin wrote:
> >>> So, that's not permitted. `free` can't be called with a dangling pointer. The
> >>> kernel free functions (*1) can't handle it, and I can't detect it, since a
> >>> dangling pointer does not have a descrete value.
> >>
> >> That is true, but only if we do not have access to the old layout of the
> >> allocation. If we add `old_layout` as a parameter, then we can handle
> >> dangling pointers.
> > 
> > Then we'd need `free` to be `fn free(ptr: NonNull<u8>, layout: Layout)` just to
> > compare whether `ptr.as_ptr() == layout.align() as _`. Same for `realloc`, but
> > that's less weird.
> 
> I don't think that's a problem (though we would check against the size
> and not compare the address!). `Allocator` from stdlib also has the
> extra argument.

Because `Allocator` from stdlib actually needs it, e.g. they have to open code
`realloc`, since userspace allocators don't give proper alignment guarantees.

Again, the kernel allocators neither need, nor take and honor this extra
information.

> 
> > It's also not that we safe code with that. `Box`, `Vec`, any other user, still
> > would have to create the `Layout` before they call `A::free`.
> 
> But for `Box` it would just be `Layout::<T>::new()` and `Vec` needs
> `Layout::<T>::new().repeat(self.cap)`.

Let's take `Vec` for instance, there it's either

current code
------------
```
	if cap != 0 {
		unsafe { A::free(self.ptr.as_non_null().cast()) };
	}
```

your proposal
-------------
```
	let layout = Layout::<T>::array(self.cap).unwrap();
	unsafe { A::free(self.ptr.as_non_null().cast(), layout) };
```

I really don't see how that's an improvement.

> 
> Though for `repeat` we need the `alloc_layout_extra` feature, which is
> an argument against doing this.
> 
> >>> Surely, we could also let the caller pass the old alignment, but this all sounds
> >>> complicated for something that is very trivial for the caller to take care of,
> >>> i.e. just don't try to free something that was never actually allocated.
> >>>
> >>> It can also lead to subtle bugs, e.g. what if someone calls `Box::from_raw` for
> >>> a ZST with some other random pointer? Currently, that doesn't hurt us, which for
> >>> robustness, seems to be a good thing.
> >>
> >> I think we should forbid that. To me it's just plain wrong to take a
> >> random integer literal and cast it to a ZST. IIRC it even is UB if that
> >> points to a previously allocated object that has been freed (but I don't
> >> remember where I read it...).
> > 
> > I think my argument about robustness still holds even if we forbid it.
> > 
> > The documentation says "For operations of size zero, every pointer is valid,
> > including the null pointer." [1]
> 
> How does this increase robustness? I am not allowed to call `free` with
> a random pointer, only pointers returned by that allocator. The same
> should also be true for `Box::from_raw`. That way the ZST dangling
> pointer stuff leaks into that API.

This point was about your first proposal to use the alignment. With cosidering
only the alignment we can't handle the case where `Box::from_raw` is called with
a random pointer for a ZST, which *technically* isn't illegal. We can define it
as illegal, but I'd consider it to be more robust, if we don't oops in case.

But as you say checking the size instead of the alignment does not have this
problem.

> 
> > [1] https://doc.rust-lang.org/std/ptr/index.html
> > 
> >>
> >> Also if we use the size of the old layout instead of comparing alignment
> >> with the address of the pointer, then we avoid this issue.
> > 
> > That is just another problem when passing the old `Layout` (or maybe just the
> > old size as usize). Neither do we need the old size, nor do we honor it with any
> > kernel allocator. This has the following implications:
> > 
> > (1) We never see any error if the old size that is passed is garbage (unless
> >     it's non-zero, when it should be zero and vice versa), which is bad.
> 
> We could add debug support for that though?

And add even more complexity just to avoid a simple `if !zero` check before
calling `free`? I don't like that.

Just to clarify, I'm not against passing the old layout in general. But I really
don't want to pass something in that is not required *and* not honored by a
single kernel allocator.

IMO, the only other valid reason to accept unneeded arguments would be if we
could use the `Allocator` interface from stdlib.

> 
> > (2) We'd need `free` to be `fn free(ptr: NonNull<u8>, size: usize)`, which is
> >     confusing, because it implies that an actual free relies on this size for
> >     freeing the memory.
> 
> I don't think that it is confusing to ask for the old layout.

It is always confusing if a function asks for information that it doesn't need
and doesn't consider, because asking for it in the first place creates the
impression that it is indeed needed and considered.

> 
> > If we want to avoid (1) and (2), we'd need to make it
> > `fn free(ptr: NonNull<u8>, zero: bool)` instead, but then also the caller can
> > just check this boolean and conditionally call `free`.
> 
> Yeah having `free` with a `zero: bool` sounds like a bad idea.
> 
> > I don't really see why it's better to let `free` do the `if !zero` check.
> 
> You did not reply to my last argument:
> 
> >> I think it's better to just let `Box` and `Vec` figure out if calling `free` is
> >> the right thing to do. The code for that is simple and obvious, i.e. check if
> >> `T` is a ZST.
> >
> > I don't think that it is as simple as you make it out to be. To me this
> > is functionality that we can move into one place and never have to think
> > about again.
> > Also if we at some point decide to add some sort of debugging allocator
> > (am I right in assuming that such a thing already exists for C?) then we

The C side allocators have quite a lot of debugging capabilities, but there is
no separate one.

> > might want to tag on extra data in the allocation, in that case it would
> > be very useful if the allocator also saw zero-sized allocations, since
> > we should check all allocations.

What would such a debugging allocator do on the Rust side?

The allocators we have are just simple wrappers around the real kernel
allocators from the C side.

I don't really see the need for some sort of debugging allocator.

  parent reply	other threads:[~2024-08-08  9:42 UTC|newest]

Thread overview: 100+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-05 15:19 [PATCH v4 00/28] Generic `Allocator` support for Rust Danilo Krummrich
2024-08-05 15:19 ` [PATCH v4 01/28] rust: alloc: add `Allocator` trait Danilo Krummrich
2024-08-06 15:00   ` Alice Ryhl
2024-08-06 16:03   ` Benno Lossin
2024-08-06 18:30     ` Danilo Krummrich
2024-08-06 20:04       ` Benno Lossin
2024-08-07  9:36         ` Danilo Krummrich
2024-08-07 20:00           ` Benno Lossin
2024-08-07 18:19   ` Gary Guo
2024-08-05 15:19 ` [PATCH v4 02/28] rust: alloc: separate `aligned_size` from `krealloc_aligned` Danilo Krummrich
2024-08-06 16:06   ` Benno Lossin
2024-08-05 15:19 ` [PATCH v4 03/28] rust: alloc: rename `KernelAllocator` to `Kmalloc` Danilo Krummrich
2024-08-06 16:07   ` Benno Lossin
2024-08-07 18:22   ` Gary Guo
2024-08-05 15:19 ` [PATCH v4 04/28] rust: alloc: implement `Allocator` for `Kmalloc` Danilo Krummrich
2024-08-06 16:51   ` Benno Lossin
2024-08-06 18:55     ` Danilo Krummrich
2024-08-07  7:14       ` Benno Lossin
2024-08-07 10:11         ` Danilo Krummrich
2024-08-07 20:15           ` Benno Lossin
2024-08-07 23:05             ` Danilo Krummrich
2024-08-08  8:55               ` Benno Lossin
2024-08-08  9:02                 ` Benno Lossin
2024-08-08  9:42                 ` Danilo Krummrich [this message]
2024-08-05 15:19 ` [PATCH v4 05/28] rust: alloc: add module `allocator_test` Danilo Krummrich
2024-08-06 16:54   ` Benno Lossin
2024-08-06 18:58     ` Danilo Krummrich
2024-08-07  7:20       ` Benno Lossin
2024-08-07 10:16         ` Danilo Krummrich
2024-08-05 15:19 ` [PATCH v4 06/28] rust: alloc: implement `Vmalloc` allocator Danilo Krummrich
2024-08-06 17:00   ` Benno Lossin
2024-08-06 19:01     ` Danilo Krummrich
2024-08-07  7:23       ` Benno Lossin
2024-08-05 15:19 ` [PATCH v4 07/28] rust: alloc: implement `KVmalloc` allocator Danilo Krummrich
2024-08-05 15:19 ` [PATCH v4 08/28] rust: types: implement `Unique<T>` Danilo Krummrich
2024-08-06 17:22   ` Benno Lossin
2024-08-06 17:28     ` Miguel Ojeda
2024-08-06 23:16       ` Danilo Krummrich
2024-08-06 23:12     ` Danilo Krummrich
2024-08-07  7:27       ` Benno Lossin
2024-08-07 10:13         ` Danilo Krummrich
2024-08-05 15:19 ` [PATCH v4 09/28] rust: alloc: implement kernel `Box` Danilo Krummrich
2024-08-06 19:47   ` Benno Lossin
2024-08-06 23:01     ` Danilo Krummrich
2024-08-07  7:49       ` Benno Lossin
2024-08-07  7:51         ` Alice Ryhl
2024-08-07  8:01           ` Benno Lossin
2024-08-07 10:44             ` Danilo Krummrich
2024-08-07 10:38         ` Danilo Krummrich
2024-08-07 19:45           ` Benno Lossin
2024-08-08 17:44         ` Danilo Krummrich
2024-08-08 19:44           ` Benno Lossin
2024-08-05 15:19 ` [PATCH v4 10/28] rust: treewide: switch to our kernel `Box` type Danilo Krummrich
2024-08-07 12:42   ` Alice Ryhl
2024-08-07 20:57   ` Benno Lossin
2024-08-07 21:16     ` Benno Lossin
2024-08-07 23:08     ` Danilo Krummrich
2024-08-05 15:19 ` [PATCH v4 11/28] rust: alloc: remove `BoxExt` extension Danilo Krummrich
2024-08-08  6:48   ` Benno Lossin
2024-08-05 15:19 ` [PATCH v4 12/28] rust: alloc: add `Box` to prelude Danilo Krummrich
2024-08-08  6:49   ` Benno Lossin
2024-08-05 15:19 ` [PATCH v4 13/28] rust: alloc: import kernel `Box` type in types.rs Danilo Krummrich
2024-08-05 15:19 ` [PATCH v4 14/28] rust: alloc: import kernel `Box` type in init.rs Danilo Krummrich
2024-08-05 15:19 ` [PATCH v4 15/28] rust: alloc: implement kernel `Vec` type Danilo Krummrich
2024-08-05 15:19 ` [PATCH v4 16/28] rust: alloc: implement `IntoIterator` for `Vec` Danilo Krummrich
2024-08-05 15:19 ` [PATCH v4 17/28] rust: alloc: implement `collect` for `IntoIter` Danilo Krummrich
2024-08-05 15:19 ` [PATCH v4 18/28] rust: treewide: switch to the kernel `Vec` type Danilo Krummrich
2024-08-07 13:47   ` Alice Ryhl
2024-08-08  9:08   ` Benno Lossin
2024-08-05 15:19 ` [PATCH v4 19/28] rust: alloc: remove `VecExt` extension Danilo Krummrich
2024-08-07 12:42   ` Alice Ryhl
2024-08-08  9:14   ` Benno Lossin
2024-08-05 15:19 ` [PATCH v4 20/28] rust: alloc: add `Vec` to prelude Danilo Krummrich
2024-08-07 13:55   ` Alice Ryhl
2024-08-08  8:40   ` Benno Lossin
2024-08-05 15:19 ` [PATCH v4 21/28] rust: alloc: remove `GlobalAlloc` and `krealloc_aligned` Danilo Krummrich
2024-08-06 19:07   ` Björn Roy Baron
2024-08-06 21:14     ` Miguel Ojeda
2024-08-07 21:23   ` Benno Lossin
2024-08-07 23:16     ` Danilo Krummrich
2024-08-05 15:19 ` [PATCH v4 22/28] rust: error: use `core::alloc::LayoutError` Danilo Krummrich
2024-08-07 13:55   ` Alice Ryhl
2024-08-08  7:42   ` Benno Lossin
2024-08-05 15:19 ` [PATCH v4 23/28] rust: error: check for config `test` in `Error::name` Danilo Krummrich
2024-08-07 13:54   ` Alice Ryhl
2024-08-05 15:19 ` [PATCH v4 24/28] rust: alloc: implement `contains` for `Flags` Danilo Krummrich
2024-08-07 13:53   ` Alice Ryhl
2024-08-05 15:19 ` [PATCH v4 25/28] rust: alloc: implement `Cmalloc` in module allocator_test Danilo Krummrich
2024-08-08  9:35   ` Benno Lossin
2024-08-08 10:07     ` Danilo Krummrich
2024-08-05 15:19 ` [PATCH v4 26/28] rust: str: test: replace `alloc::format` Danilo Krummrich
2024-08-07 13:51   ` Alice Ryhl
2024-08-08  7:22   ` Benno Lossin
2024-08-12 13:07     ` Danilo Krummrich
2024-08-05 15:19 ` [PATCH v4 27/28] rust: alloc: update module comment of alloc.rs Danilo Krummrich
2024-08-07 13:50   ` Alice Ryhl
2024-08-08  6:59   ` Benno Lossin
2024-08-05 15:19 ` [PATCH v4 28/28] kbuild: rust: remove the `alloc` crate Danilo Krummrich
2024-08-08  6:58   ` Benno Lossin
2024-08-08  9:45   ` Benno Lossin

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=ZrSS_N1R7zkiH_-E@pollux \
    --to=dakr@kernel.org \
    --cc=a.hindborg@samsung.com \
    --cc=acurrid@nvidia.com \
    --cc=airlied@redhat.com \
    --cc=ajanulgu@redhat.com \
    --cc=akpm@linux-foundation.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=benno.lossin@proton.me \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=boris.brezillon@collabora.com \
    --cc=cjia@nvidia.com \
    --cc=daniel.almeida@collabora.com \
    --cc=faith.ekstrand@collabora.com \
    --cc=gary@garyguo.net \
    --cc=jhubbard@nvidia.com \
    --cc=lina@asahilina.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=lyude@redhat.com \
    --cc=mcanal@igalia.com \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=wedsonaf@gmail.com \
    --cc=zhiw@nvidia.com \
    /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;
as well as URLs for NNTP newsgroup(s).