aboutsummaryrefslogtreecommitdiffstats
path: root/samples/rust/rust_driver_pci.rs
diff options
context:
space:
mode:
authorDanilo Krummrich <[email protected]>2025-06-26 20:00:41 +0000
committerDanilo Krummrich <[email protected]>2025-06-28 16:08:50 +0000
commitf5d3ef25d238901a76fe0277787afa44f7714739 (patch)
tree9c57a14c2cddb8d78f710f8d26e6896398650486 /samples/rust/rust_driver_pci.rs
parentrust: devres: replace Devres::new_foreign_owned() (diff)
downloadkernel-f5d3ef25d238901a76fe0277787afa44f7714739.tar.gz
kernel-f5d3ef25d238901a76fe0277787afa44f7714739.zip
rust: devres: get rid of Devres' inner Arc
So far Devres uses an inner memory allocation and reference count, i.e. an inner Arc, in order to ensure that the devres callback can't run into a use-after-free in case where the Devres object is dropped while the devres callback runs concurrently. Instead, use a completion in order to avoid a potential UAF: In Devres::drop(), if we detect that we can't remove the devres action anymore, we wait for the completion that is completed from the devres callback. If, in turn, we were able to successfully remove the devres action, we can just go ahead. This, again, allows us to get rid of the internal Arc, and instead let Devres consume an `impl PinInit<T, E>` in order to return an `impl PinInit<Devres<T>, E>`, which enables us to get away with less memory allocations. Additionally, having the resulting explicit synchronization in Devres::drop() prevents potential subtle undesired side effects of the devres callback dropping the final Arc reference asynchronously within the devres callback. Reviewed-by: Benno Lossin <[email protected]> Reviewed-by: Boqun Feng <[email protected]> Link: https://lore.kernel.org/r/[email protected] [ Move '# Invariants' below '# Examples'. - Danilo ] Signed-off-by: Danilo Krummrich <[email protected]>
Diffstat (limited to 'samples/rust/rust_driver_pci.rs')
-rw-r--r--samples/rust/rust_driver_pci.rs19
1 files changed, 10 insertions, 9 deletions
diff --git a/samples/rust/rust_driver_pci.rs b/samples/rust/rust_driver_pci.rs
index 15147e4401b2..5c35f1414172 100644
--- a/samples/rust/rust_driver_pci.rs
+++ b/samples/rust/rust_driver_pci.rs
@@ -25,8 +25,10 @@ impl TestIndex {
const NO_EVENTFD: Self = Self(0);
}
+#[pin_data(PinnedDrop)]
struct SampleDriver {
pdev: ARef<pci::Device>,
+ #[pin]
bar: Devres<Bar0>,
}
@@ -73,13 +75,11 @@ impl pci::Driver for SampleDriver {
pdev.enable_device_mem()?;
pdev.set_master();
- let bar = pdev.iomap_region_sized::<{ Regs::END }>(0, c_str!("rust_driver_pci"))?;
-
- let drvdata = KBox::new(
- Self {
+ let drvdata = KBox::pin_init(
+ try_pin_init!(Self {
pdev: pdev.into(),
- bar,
- },
+ bar <- pdev.iomap_region_sized::<{ Regs::END }>(0, c_str!("rust_driver_pci")),
+ }),
GFP_KERNEL,
)?;
@@ -90,12 +90,13 @@ impl pci::Driver for SampleDriver {
Self::testdev(info, bar)?
);
- Ok(drvdata.into())
+ Ok(drvdata)
}
}
-impl Drop for SampleDriver {
- fn drop(&mut self) {
+#[pinned_drop]
+impl PinnedDrop for SampleDriver {
+ fn drop(self: Pin<&mut Self>) {
dev_dbg!(self.pdev.as_ref(), "Remove Rust PCI driver sample.\n");
}
}