From e873c74132f0c5f1452816cd9bb26208f0bba1e1 Mon Sep 17 00:00:00 2001 From: Shivank Garg Date: Sat, 22 Aug 2026 19:22:05 +0000 Subject: dmaengine: fix use-after-free in dma_chan_put() and dma_release_channel() When dma_device_put() drops the last reference on chan->device->ref, dma_device_release() runs and may free the dma_device along with its channels. dma_chan_put() then still reads chan->device->owner via dma_chan_to_owner() for the trailing module_put(). KASAN catches it: slab-use-after-free in dma_chan_put+0x3e6/0x4c0 Read of size 8 by task insmod/6319 Freed by task 6319: kfree+0x225/0x470 dma_chan_put+0x395/0x4c0 dmaengine_put+0xf8/0x160 Cache the module owner in dma_chan_put() before the put so the trailing module_put() does not need chan->device. Fixes: 8ad342a86359 ("dmaengine: Add reference counting to dma_device struct") Suggested-by: Sashiko Link: https://sashiko.dev/#/patchset/20260518-dmaengine-kref-fix-v1-1-4d6125048fb7@amd.com Reviewed-by: Frank Li Reviewed-by: Logan Gunthorpe Signed-off-by: Shivank Garg Link: https://patch.msgid.link/20260822-dmaengine-kref-fix-v5-3-d4a4ee47d927@amd.com Signed-off-by: Vinod Koul --- rust/helpers/io.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 rust/helpers/io.c (limited to 'rust/helpers/io.c') diff --git a/rust/helpers/io.c b/rust/helpers/io.c new file mode 100644 index 000000000..308950aae --- /dev/null +++ b/rust/helpers/io.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include + +#ifdef CONFIG_HAS_IOMEM +__rust_helper void __iomem *rust_helper_ioremap(phys_addr_t offset, size_t size) +{ + return ioremap(offset, size); +} + +__rust_helper void __iomem *rust_helper_ioremap_np(phys_addr_t offset, + size_t size) +{ + return ioremap_np(offset, size); +} + +__rust_helper void rust_helper_iounmap(void __iomem *addr) +{ + iounmap(addr); +} +#endif /* CONFIG_HAS_IOMEM */ + +__rust_helper void rust_helper_memcpy_fromio(void *dst, + const volatile void __iomem *src, + size_t count) +{ + memcpy_fromio(dst, src, count); +} + +__rust_helper void rust_helper_memcpy_toio(volatile void __iomem *dst, + const void *src, size_t count) +{ + memcpy_toio(dst, src, count); +} + +__rust_helper u8 rust_helper_readb(const void __iomem *addr) +{ + return readb(addr); +} + +__rust_helper u16 rust_helper_readw(const void __iomem *addr) +{ + return readw(addr); +} + +__rust_helper u32 rust_helper_readl(const void __iomem *addr) +{ + return readl(addr); +} + +#ifdef CONFIG_64BIT +__rust_helper u64 rust_helper_readq(const void __iomem *addr) +{ + return readq(addr); +} +#endif + +__rust_helper void rust_helper_writeb(u8 value, void __iomem *addr) +{ + writeb(value, addr); +} + +__rust_helper void rust_helper_writew(u16 value, void __iomem *addr) +{ + writew(value, addr); +} + +__rust_helper void rust_helper_writel(u32 value, void __iomem *addr) +{ + writel(value, addr); +} + +#ifdef CONFIG_64BIT +__rust_helper void rust_helper_writeq(u64 value, void __iomem *addr) +{ + writeq(value, addr); +} +#endif + +__rust_helper u8 rust_helper_readb_relaxed(const void __iomem *addr) +{ + return readb_relaxed(addr); +} + +__rust_helper u16 rust_helper_readw_relaxed(const void __iomem *addr) +{ + return readw_relaxed(addr); +} + +__rust_helper u32 rust_helper_readl_relaxed(const void __iomem *addr) +{ + return readl_relaxed(addr); +} + +#ifdef CONFIG_64BIT +__rust_helper u64 rust_helper_readq_relaxed(const void __iomem *addr) +{ + return readq_relaxed(addr); +} +#endif + +__rust_helper void rust_helper_writeb_relaxed(u8 value, void __iomem *addr) +{ + writeb_relaxed(value, addr); +} + +__rust_helper void rust_helper_writew_relaxed(u16 value, void __iomem *addr) +{ + writew_relaxed(value, addr); +} + +__rust_helper void rust_helper_writel_relaxed(u32 value, void __iomem *addr) +{ + writel_relaxed(value, addr); +} + +#ifdef CONFIG_64BIT +__rust_helper void rust_helper_writeq_relaxed(u64 value, void __iomem *addr) +{ + writeq_relaxed(value, addr); +} +#endif + +__rust_helper resource_size_t rust_helper_resource_size(struct resource *res) +{ + return resource_size(res); +} + +__rust_helper struct resource * +rust_helper_request_mem_region(resource_size_t start, resource_size_t n, + const char *name) +{ + return request_mem_region(start, n, name); +} + +__rust_helper void rust_helper_release_mem_region(resource_size_t start, + resource_size_t n) +{ + release_mem_region(start, n); +} + +__rust_helper struct resource *rust_helper_request_region(resource_size_t start, + resource_size_t n, + const char *name) +{ + return request_region(start, n, name); +} + +__rust_helper struct resource * +rust_helper_request_muxed_region(resource_size_t start, resource_size_t n, + const char *name) +{ + return request_muxed_region(start, n, name); +} + +__rust_helper void rust_helper_release_region(resource_size_t start, + resource_size_t n) +{ + release_region(start, n); +} -- cgit v1.3.1