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: <DFXV1QMQMTRK.2W8SWGVHS2K69@kernel.org>
Date: Sun, 25 Jan 2026 18:53:15 +0100
From: "Danilo Krummrich" <dakr@...nel.org>
To: "Greg Kroah-Hartman" <gregkh@...uxfoundation.org>
Cc: "Johan Hovold" <johan@...nel.org>, "Rafael J . Wysocki"
 <rafael@...nel.org>, "Tzung-Bi Shih" <tzungbi@...nel.org>, "Bartosz
 Golaszewski" <bartosz.golaszewski@....qualcomm.com>, "Linus Walleij"
 <linusw@...nel.org>, "Jonathan Corbet" <corbet@....net>, "Shuah Khan"
 <shuah@...nel.org>, "Laurent Pinchart" <laurent.pinchart@...asonboard.com>,
 "Wolfram Sang" <wsa+renesas@...g-engineering.com>, "Simona Vetter"
 <simona.vetter@...ll.ch>, "Dan Williams" <dan.j.williams@...el.com>, "Jason
 Gunthorpe" <jgg@...dia.com>, <linux-doc@...r.kernel.org>,
 <linux-kselftest@...r.kernel.org>, <linux-kernel@...r.kernel.org>
Subject: Re: [PATCH 0/3] Revert "revocable: Revocable resource management"

On Sun Jan 25, 2026 at 1:47 PM CET, Greg Kroah-Hartman wrote:
> On Sat, Jan 24, 2026 at 08:08:28PM +0100, Danilo Krummrich wrote:
>> But to be fair, I also want to point out that there is a quite significant
>> difference regarding the usefulness of the revocable concept in C compared to in
>> Rust due to language capabilities.
>
> True, but we do need something.  I took these patches without a real
> user as a base for us to start working off of.  The rust implementation
> has shown that the design-pattern is a good solution for the problem,
> and so I feel we should work with it and try to get this working
> properly.

I agree, it's a matter of figuring out the best way to adopt this pattern. (For
those reading along, [1] details the Rust implementation to illustrate why it
may not make sense to adopt it in the same way).

> So I don't want to take these reverts, let's try this out, by putting this
> into the driver core now, we have the base to experiment with in a "safe" way
> in lots of different driver subsytems at the same time.

I also don't think this should be reverted -- I think it makes sense to start
experimenting to figure out what's the best way to adopt this pattern.

I think DRM has already shown interest in adopting this, and I think I have also
seen patch series doing preparation work to be able to adopt this pattern as
well.

Perhaps, to address some of the concerns, a good middle ground could be to mark
the feature as experimental with a separate Kconfig in the meantime?

--

[1] Revocable in Rust

In Rust (most) device resources are only ever handed out to drivers within an
opaque container type specific for device resources, hence it is named
Devres<T>.

The Devres container type uses the Revocable type internally to protect the
actual device resource; the resource is released automatically once the
corresponding device is unbound from the driver (for which it uses the "normal"
devres infrastructure).

There are mainly two ways to access a device resource with a Devres container:
Devres::access() and Devres::try_access().

Devres::access() provides a zero-cost access to the inner device resource, but
requires a proof that it is called from a scope where it is guaranteed that the
device remains bound. This is achieved by Devres::access() taking a
&Device<Bound> argument, i.e. a reference (not reference count) of a device that
is guaranteed to be bound for the entire lifetime of the reference.

Let's have a look at an example with an IRQ handler:

	struct MyIrqData {
	    bar: Devres<pci::Bar>,
	}

	impl irq::Handler for MyIrqData {
	    fn handle(&self, dev: &Device<Bound>) -> IrqReturn {
	        // Directly access the inner `pci::Bar`; fails if the resource
	        // did not originate from `dev`.
	        //
	        // (Internally, this is just a pointer comparison between `dev`
	        // and the device the `Devres` container has been created with.)
	        if let Ok(bar) = self.bar.access(dev) else {
	            return IrqReturn::None;
	        }

	        // `bar` is a `&pci::Bar`; no (S)RCU read side critical section
	        // involved.
	        bar.write32(...);

	        IrqReturn::Handled
	    }
	}

Since the Rust IRQ handler always guarantees that it won't race with device
unbind, we can provide a &Device<Bound> cookie and hence directly access the
device resource with no cost. Due to the type system representation of the
device context state, this is checked at compile time.

We can do this for anything that guarantees a scope where the device must be
bound. For instance, if we guarantee that a workqueue is torn down on device
unbind, we can provide a &Device<Bound> cookie for all work items scheduled on
this workqueue. The same applies to subsystem and filesystem callbacks etc.

But, if we are in a scope where we don't have a &Device<Bound>, it means that
this may be executed after device unbind. Consequently, drivers can't call
Devres::access() for direct access of the device resource (because it may be a
UAF) and, instead, have to fall back to Devres::try_access() and friends.

Let's take some DRM IOCTL for instance:

	struct MyDriver {
	    bar: Devres<pci::Bar>,
	}

	fn ioctl_vm_create(
	    drm: &drm::Device<MyDriver>,
	    req: &mut uapi::drm_mydriver_vm_create,
	    file: &drm::File<MyDriverFile>,
	) -> Result<u32> {
	    // Runs the closure in an (S)RCU read side critical section if the
	    // resource is available, returns ENXIO otherwise.
	    drm.bar.try_access_with(|bar| {
	        // (S)RCU read side critical section starts here.

	        bar.write32(...);

	        // (S)RCU read side critical section ends here.
	    }).ok_or(ENXIO)?;

	    Ok(0)
	}

I think those examples make it obvious why a revocable implementation on the C
side can't provide the same value and ergonomics due to language limitations,
yet I think it makes sense to start experimenting how subsystems can adopt this
design-pattern in C.

One additional note, while this overall can come across a bit paranoid, it
achieves a clear goal: It becomes impossible for drivers to mess this up and
create memory safety bugs, while at the same time causing zero overhead in hot
paths, that can be proven to not have a potential for such bugs in the first
place.

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ