提交 f7f16389 编写于 作者: D Ding Hui

iommu/arm-smmu-v3: Fix UAF when handle evt during iommu group removing

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 395ad89d,
move arm_smmu_remove_master() before iommu_group_remove_device(),
and hold mutex to protect finding master and subsequent handling.

Fixes: b525f0a6 ("iommu/arm-smmu-v3: Add stall support for platform devices")
Signed-off-by: NDing Hui <dinghui@sangfor.com.cn>
上级 a5f1c660
...@@ -1742,7 +1742,8 @@ arm_smmu_find_master(struct arm_smmu_device *smmu, u32 sid) ...@@ -1742,7 +1742,8 @@ arm_smmu_find_master(struct arm_smmu_device *smmu, u32 sid)
struct arm_smmu_stream *stream; struct arm_smmu_stream *stream;
struct arm_smmu_master_data *master = NULL; struct arm_smmu_master_data *master = NULL;
mutex_lock(&smmu->streams_mutex); lockdep_assert_held(&smmu->streams_mutex);
node = smmu->streams.rb_node; node = smmu->streams.rb_node;
while (node) { while (node) {
stream = rb_entry(node, struct arm_smmu_stream, 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) ...@@ -1755,7 +1756,6 @@ arm_smmu_find_master(struct arm_smmu_device *smmu, u32 sid)
break; break;
} }
} }
mutex_unlock(&smmu->streams_mutex);
return master; return master;
} }
...@@ -1791,9 +1791,12 @@ static int arm_smmu_handle_evt(struct arm_smmu_device *smmu, u64 *evt) ...@@ -1791,9 +1791,12 @@ static int arm_smmu_handle_evt(struct arm_smmu_device *smmu, u64 *evt)
if (evt[1] & EVTQ_1_S2) if (evt[1] & EVTQ_1_S2)
return -EFAULT; return -EFAULT;
mutex_lock(&smmu->streams_mutex);
master = arm_smmu_find_master(smmu, sid); master = arm_smmu_find_master(smmu, sid);
if (!master) if (!master) {
return -EINVAL; ret = -EINVAL;
goto out_unlock;
}
/* /*
* The domain is valid until the fault returns, because detach() flushes * 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) ...@@ -1833,6 +1836,8 @@ static int arm_smmu_handle_evt(struct arm_smmu_device *smmu, u64 *evt)
arm_smmu_page_response(master->dev, &resp); arm_smmu_page_response(master->dev, &resp);
} }
out_unlock:
mutex_unlock(&smmu->streams_mutex);
return ret; return ret;
} }
...@@ -2935,8 +2940,8 @@ static void arm_smmu_remove_device(struct device *dev) ...@@ -2935,8 +2940,8 @@ static void arm_smmu_remove_device(struct device *dev)
iopf_queue_remove_device(dev); iopf_queue_remove_device(dev);
if (master->ste.assigned) if (master->ste.assigned)
arm_smmu_detach_dev(dev); arm_smmu_detach_dev(dev);
iommu_group_remove_device(dev);
arm_smmu_remove_master(smmu, master); arm_smmu_remove_master(smmu, master);
iommu_group_remove_device(dev);
iommu_device_unlink(&smmu->iommu, dev); iommu_device_unlink(&smmu->iommu, dev);
kfree(master); kfree(master);
iommu_fwspec_free(dev); iommu_fwspec_free(dev);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册