driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I6WKM7 CVE: NA
--------
A use-after-free issue like following:
[ 2257.819189] arm-smmu-v3 arm-smmu-v3.4.auto: EVTQ overflow detected -- events lost [ 2257.819197] arm-smmu-v3 arm-smmu-v3.4.auto: event 0x10 received: [ 2257.819199] arm-smmu-v3 arm-smmu-v3.4.auto: 0x0000820000000010 [ 2257.819201] arm-smmu-v3 arm-smmu-v3.4.auto: 0x0000020000000000 [ 2257.819202] arm-smmu-v3 arm-smmu-v3.4.auto: 0x00000000dfea7218 [ 2257.819206] iommu: Removing device 0000:82:00.0 from group 49 [ 2257.819207] arm-smmu-v3 arm-smmu-v3.4.auto: 0x00000000dfea7000 [ 2257.819211] arm-smmu-v3 arm-smmu-v3.4.auto: event 0x10 received: [ 2257.819212] arm-smmu-v3 arm-smmu-v3.4.auto: 0x0000820000000010 [ 2257.819214] arm-smmu-v3 arm-smmu-v3.4.auto: 0x0000020000000000 [ 2257.819215] arm-smmu-v3 arm-smmu-v3.4.auto: 0x00000000dfea722c [ 2257.819216] arm-smmu-v3 arm-smmu-v3.4.auto: 0x00000000dfea7000 [ 2257.819218] ================================================================== [ 2257.819228] BUG: KASAN: use-after-free in iommu_report_device_fault+0x520/0x5c0 [ 2257.819230] Read of size 8 at addr ffffa02c516c1320 by task irq/63-arm-smmu/483 [ 2257.819231] [ 2257.819235] CPU: 25 PID: 483 Comm: irq/63-arm-smmu Kdump: loaded Tainted: G OE 4.19.90-2205.3.0.0149.oe1.aarch64+debug #1 [ 2257.819236] Hardware name: Huawei S920S00/BC82AMDGK, BIOS 1.68 11/10/2020 [ 2257.819237] Call trace: [ 2257.819240] dump_backtrace+0x0/0x320 [ 2257.819242] show_stack+0x24/0x30 [ 2257.819246] dump_stack+0xdc/0x128 [ 2257.819251] print_address_description+0x68/0x278 [ 2257.819253] kasan_report+0x1e4/0x308 [ 2257.819254] __asan_report_load8_noabort+0x30/0x40 [ 2257.819257] iommu_report_device_fault+0x520/0x5c0 [ 2257.819260] arm_smmu_handle_evt+0x300/0x428 [ 2257.819261] arm_smmu_evtq_thread+0x27c/0x460 [ 2257.819264] irq_thread_fn+0x88/0x140 [ 2257.819266] irq_thread+0x190/0x318 [ 2257.819268] kthread+0x2a4/0x320 [ 2257.819270] ret_from_fork+0x10/0x18 [ 2257.819271] [ 2257.819273] Allocated by task 95166: [ 2257.819275] kasan_kmalloc+0xd0/0x178 [ 2257.819277] kmem_cache_alloc_trace+0x100/0x210 [ 2257.819279] iommu_group_add_device+0x254/0xe18 [ 2257.819280] iommu_group_get_for_dev+0x198/0x480 [ 2257.819282] arm_smmu_add_device+0x424/0x988 [ 2257.819284] iort_iommu_configure+0x33c/0x5b8 [ 2257.819287] acpi_dma_configure+0x9c/0xf8 [ 2257.819289] pci_dma_configure+0x124/0x158 [ 2257.819291] dma_configure+0x5c/0x80 [ 2257.819294] really_probe+0xcc/0x920 [ 2257.819296] driver_probe_device+0x224/0x308 [ 2257.819298] __device_attach_driver+0x154/0x260 [ 2257.819299] bus_for_each_drv+0xe4/0x178 [ 2257.819301] __device_attach+0x1bc/0x2a8 [ 2257.819302] device_attach+0x24/0x30 [ 2257.819304] pci_bus_add_device+0x7c/0xe8 [ 2257.819305] pci_bus_add_devices+0x70/0x168 [ 2257.819307] pci_bus_add_devices+0x114/0x168 [ 2257.819308] pci_rescan_bus+0x38/0x48 [ 2257.819310] bus_rescan_store+0xc4/0xe8 [ 2257.819312] bus_attr_store+0x70/0x98 [ 2257.819314] sysfs_kf_write+0x104/0x170 [ 2257.819316] kernfs_fop_write+0x23c/0x430 [ 2257.819319] __vfs_write+0x7c/0xe8 [ 2257.819320] vfs_write+0x12c/0x3d0 [ 2257.819321] ksys_write+0xd4/0x1d8 [ 2257.819322] __arm64_sys_write+0x70/0xa0 [ 2257.819325] el0_svc_common+0xfc/0x278 [ 2257.819327] el0_svc_handler+0x50/0xc0 [ 2257.819329] el0_svc+0x8/0x1b0 [ 2257.819329] [ 2257.819330] Freed by task 95166: [ 2257.819332] __kasan_slab_free+0x114/0x200 [ 2257.819334] kasan_slab_free+0x10/0x18 [ 2257.819335] kfree+0x80/0x1f0 [ 2257.819337] iommu_group_remove_device+0x27c/0x560 [ 2257.819338] arm_smmu_remove_device+0xe8/0x190 [ 2257.819339] iommu_bus_notifier+0x134/0x248 [ 2257.819342] notifier_call_chain+0xb0/0x140 [ 2257.819343] blocking_notifier_call_chain+0x6c/0xd8 [ 2257.819344] device_del+0x578/0x940 [ 2257.819346] pci_remove_bus_device+0x114/0x290 [ 2257.819347] pci_stop_and_remove_bus_device_locked+0x2c/0x40 [ 2257.819349] remove_store+0xdc/0xe8 [ 2257.819352] dev_attr_store+0x60/0x80 [ 2257.819353] sysfs_kf_write+0x104/0x170 [ 2257.819354] kernfs_fop_write+0x23c/0x430 [ 2257.819355] __vfs_write+0x7c/0xe8 [ 2257.819357] vfs_write+0x12c/0x3d0 [ 2257.819358] ksys_write+0xd4/0x1d8 [ 2257.819359] __arm64_sys_write+0x70/0xa0 [ 2257.819361] el0_svc_common+0xfc/0x278 [ 2257.819362] el0_svc_handler+0x50/0xc0 [ 2257.819364] el0_svc+0x8/0x1b0 [ 2257.819364]
T0 T1 --------------------------------- --------------------------------- |- arm_smmu_evtq_thread |- arm_smmu_remove_device |- arm_smmu_handle_evt |- iommu_group_remove_device |- kfree(dev->iommu_param) |- arm_smmu_find_master |- iommu_report_device_fault |- arm_smmu_remove_master |- mutex_lock( \ &dev->iommu_param->lock) // UAF
Reference upstream mainline commit 395ad89d11fd93f79a6b942e91fc409807a63c4b, move arm_smmu_remove_master() before iommu_group_remove_device(), and hold mutex to protect finding master and subsequent handling.
Fixes: b525f0a6f9b0 ("iommu/arm-smmu-v3: Add stall support for platform devices") Signed-off-by: Ding Hui dinghui@sangfor.com.cn --- drivers/iommu/arm-smmu-v3.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 3309ae6ebc0b..05cb92da6836 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -1742,7 +1742,8 @@ arm_smmu_find_master(struct arm_smmu_device *smmu, u32 sid) struct arm_smmu_stream *stream; struct arm_smmu_master_data *master = NULL;
- mutex_lock(&smmu->streams_mutex); + lockdep_assert_held(&smmu->streams_mutex); + node = smmu->streams.rb_node; while (node) { stream = rb_entry(node, struct arm_smmu_stream, node); @@ -1755,7 +1756,6 @@ arm_smmu_find_master(struct arm_smmu_device *smmu, u32 sid) break; } } - mutex_unlock(&smmu->streams_mutex);
return master; } @@ -1791,9 +1791,12 @@ static int arm_smmu_handle_evt(struct arm_smmu_device *smmu, u64 *evt) if (evt[1] & EVTQ_1_S2) return -EFAULT;
+ mutex_lock(&smmu->streams_mutex); master = arm_smmu_find_master(smmu, sid); - if (!master) - return -EINVAL; + if (!master) { + ret = -EINVAL; + goto out_unlock; + }
/* * The domain is valid until the fault returns, because detach() flushes @@ -1833,6 +1836,8 @@ static int arm_smmu_handle_evt(struct arm_smmu_device *smmu, u64 *evt) arm_smmu_page_response(master->dev, &resp); }
+out_unlock: + mutex_unlock(&smmu->streams_mutex); return ret; }
@@ -2935,8 +2940,8 @@ static void arm_smmu_remove_device(struct device *dev) iopf_queue_remove_device(dev); if (master->ste.assigned) arm_smmu_detach_dev(dev); - iommu_group_remove_device(dev); arm_smmu_remove_master(smmu, master); + iommu_group_remove_device(dev); iommu_device_unlink(&smmu->iommu, dev); kfree(master); iommu_fwspec_free(dev);