Skip to content

Commit 4f7b10f

Browse files
committed
Merge tag 'drm-misc-fixes-2026-07-17' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-fixes
drm-misc-fixes for v7.2-rc4: - Fix UAF in host1x, amdxdna. - Handle invalid firmware log in ivpu. - Fix error handling in panthor. - Handle NULL pages and backup handles in ttm_pool_backup() correctly. - Reject more invalid amdxdna command submissions. - Improve unmap and error handling on gpusvm. - Fix virtio deadlock and invalid gem detach. - Fix wrong read in ivpu. - Always synchronize for CPU in begin_cpu_udmabuf. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patch.msgid.link/7f10281e-88f5-4be5-8b42-367e7ce7c547@linux.intel.com
2 parents a13c140 + faebb7b commit 4f7b10f

12 files changed

Lines changed: 114 additions & 38 deletions

File tree

drivers/accel/amdxdna/amdxdna_ctx.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,7 @@ void amdxdna_sched_job_cleanup(struct amdxdna_sched_job *job)
577577
amdxdna_arg_bos_put(job);
578578
amdxdna_gem_put_obj(job->cmd_bo);
579579
dma_fence_put(job->fence);
580+
mmdrop(job->mm);
580581
}
581582

582583
int amdxdna_cmd_submit(struct amdxdna_client *client,
@@ -590,6 +591,10 @@ int amdxdna_cmd_submit(struct amdxdna_client *client,
590591
int ret, idx;
591592

592593
XDNA_DBG(xdna, "Command BO hdl %d, Arg BO count %d", cmd_bo_hdl, arg_bo_cnt);
594+
595+
if (!xdna->dev_info->ops->cmd_submit)
596+
return -EOPNOTSUPP;
597+
593598
job = kzalloc_flex(*job, bos, arg_bo_cnt);
594599
if (!job)
595600
return -ENOMEM;
@@ -603,6 +608,16 @@ int amdxdna_cmd_submit(struct amdxdna_client *client,
603608
ret = -EINVAL;
604609
goto free_job;
605610
}
611+
} else if (!drv_cmd) {
612+
/*
613+
* Only internal driver commands (drv_cmd != NULL) may omit a
614+
* command BO. A user command submission with the invalid handle
615+
* would leave job->cmd_bo NULL and later fault when the scheduler
616+
* dereferences it in amdxdna_cmd_set_state().
617+
*/
618+
XDNA_DBG(xdna, "Command BO handle required for user submission");
619+
ret = -EINVAL;
620+
goto free_job;
606621
}
607622

608623
ret = amdxdna_arg_bos_lookup(client, job, arg_bo_hdls, arg_bo_cnt);
@@ -628,6 +643,7 @@ int amdxdna_cmd_submit(struct amdxdna_client *client,
628643

629644
job->hwctx = hwctx;
630645
job->mm = current->mm;
646+
mmgrab(job->mm);
631647

632648
job->fence = amdxdna_fence_create(hwctx);
633649
if (!job->fence) {
@@ -662,6 +678,8 @@ int amdxdna_cmd_submit(struct amdxdna_client *client,
662678
cmd_put:
663679
amdxdna_gem_put_obj(job->cmd_bo);
664680
free_job:
681+
if (job->mm)
682+
mmdrop(job->mm);
665683
kfree(job);
666684
return ret;
667685
}

drivers/accel/ivpu/ivpu_fw_log.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ static int fw_log_from_bo(struct ivpu_device *vdev, struct ivpu_bo *bo, u32 *off
4343
ivpu_dbg(vdev, FW_BOOT, "Invalid header size 0x%x\n", log->header_size);
4444
return -EINVAL;
4545
}
46+
if (log->size < log->header_size) {
47+
ivpu_dbg(vdev, FW_BOOT, "Invalid log size 0x%x\n", log->size);
48+
return -EINVAL;
49+
}
4650
if ((char *)log + log->size > (char *)ivpu_bo_vaddr(bo) + ivpu_bo_size(bo)) {
4751
ivpu_dbg(vdev, FW_BOOT, "Invalid log size 0x%x\n", log->size);
4852
return -EINVAL;

drivers/accel/ivpu/ivpu_hw_btrs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -927,7 +927,7 @@ static void diagnose_failure_mtl(struct ivpu_device *vdev)
927927

928928
static void diagnose_failure_lnl(struct ivpu_device *vdev)
929929
{
930-
u32 reg = REGB_RD32(VPU_HW_BTRS_MTL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK;
930+
u32 reg = REGB_RD32(VPU_HW_BTRS_LNL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK;
931931

932932
if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, ATS_ERR, reg)) {
933933
ivpu_err(vdev, "ATS_ERR_LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n",

drivers/dma-buf/udmabuf.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,21 +224,22 @@ static int begin_cpu_udmabuf(struct dma_buf *buf,
224224
{
225225
struct udmabuf *ubuf = buf->priv;
226226
struct device *dev = ubuf->device->this_device;
227-
int ret = 0;
228227

229228
if (!ubuf->sg) {
230229
ubuf->sg = get_sg_table(dev, buf, direction);
231230
if (IS_ERR(ubuf->sg)) {
231+
int ret;
232+
232233
ret = PTR_ERR(ubuf->sg);
233234
ubuf->sg = NULL;
235+
return ret;
234236
} else {
235237
ubuf->sg_dir = direction;
236238
}
237-
} else {
238-
dma_sync_sgtable_for_cpu(dev, ubuf->sg, direction);
239239
}
240240

241-
return ret;
241+
dma_sync_sgtable_for_cpu(dev, ubuf->sg, direction);
242+
return 0;
242243
}
243244

244245
static int end_cpu_udmabuf(struct dma_buf *buf,

drivers/gpu/drm/drm_gpusvm.c

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,20 +1146,35 @@ static void __drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
11461146
};
11471147
bool use_iova = dma_use_iova(&svm_pages->state);
11481148

1149-
if (use_iova)
1150-
dma_iova_destroy(dev, &svm_pages->state,
1151-
svm_pages->state_offset,
1152-
svm_pages->dma_addr[0].dir, 0);
1149+
/*
1150+
* IOVA is reserved for the whole range but only the linked
1151+
* system pages (state_offset bytes) need unlinking; free the
1152+
* entire reservation to avoid leaking the device-page part.
1153+
* On the error path state_offset is 0, so just free it.
1154+
*/
1155+
if (use_iova) {
1156+
if (svm_pages->state_offset)
1157+
dma_iova_unlink(dev, &svm_pages->state, 0,
1158+
svm_pages->state_offset,
1159+
svm_pages->dma_addr[0].dir, 0);
1160+
dma_iova_free(dev, &svm_pages->state);
1161+
}
11531162

11541163
for (i = 0, j = 0; i < npages; j++) {
11551164
struct drm_pagemap_addr *addr = &svm_pages->dma_addr[j];
11561165

1157-
if (!use_iova && addr->proto == DRM_INTERCONNECT_SYSTEM)
1158-
dma_unmap_page(dev,
1159-
addr->addr,
1160-
PAGE_SIZE << addr->order,
1161-
addr->dir);
1162-
else if (dpagemap && dpagemap->ops->device_unmap)
1166+
if (addr->proto == DRM_INTERCONNECT_SYSTEM) {
1167+
/*
1168+
* Linked IOVA pages were already torn down by
1169+
* the dma_iova_unlink()/dma_iova_free() above;
1170+
* only the non-IOVA mappings need unmap here.
1171+
*/
1172+
if (!use_iova)
1173+
dma_unmap_page(dev,
1174+
addr->addr,
1175+
PAGE_SIZE << addr->order,
1176+
addr->dir);
1177+
} else if (dpagemap && dpagemap->ops->device_unmap)
11631178
dpagemap->ops->device_unmap(dpagemap,
11641179
dev, addr);
11651180
i += 1 << addr->order;
@@ -1486,7 +1501,7 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
14861501
/* Unlock and restart mapping to allocate memory. */
14871502
drm_gpusvm_notifier_unlock(gpusvm);
14881503
svm_pages->dma_addr =
1489-
kvmalloc_objs(*svm_pages->dma_addr, npages);
1504+
kvzalloc_objs(*svm_pages->dma_addr, npages);
14901505
if (!svm_pages->dma_addr) {
14911506
err = -ENOMEM;
14921507
goto err_free;
@@ -1529,6 +1544,16 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
15291544
err = -EAGAIN;
15301545
goto err_unmap;
15311546
}
1547+
1548+
/*
1549+
* Set the dpagemap as soon as the first
1550+
* device page is mapped so the err_unmap path
1551+
* can device_unmap() the device mappings that
1552+
* have already been created.
1553+
*/
1554+
drm_pagemap_get(dpagemap);
1555+
drm_pagemap_put(svm_pages->dpagemap);
1556+
svm_pages->dpagemap = dpagemap;
15321557
}
15331558
svm_pages->dma_addr[j] =
15341559
dpagemap->ops->device_map(dpagemap,
@@ -1596,12 +1621,8 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
15961621
goto err_unmap;
15971622
}
15981623

1599-
if (pagemap) {
1624+
if (pagemap)
16001625
flags.has_devmem_pages = true;
1601-
drm_pagemap_get(dpagemap);
1602-
drm_pagemap_put(svm_pages->dpagemap);
1603-
svm_pages->dpagemap = dpagemap;
1604-
}
16051626

16061627
/* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */
16071628
WRITE_ONCE(svm_pages->flags.__flags, flags.__flags);

drivers/gpu/drm/panthor/panthor_device.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,10 @@ int panthor_device_init(struct panthor_device *ptdev)
182182
return ret;
183183

184184
#ifdef CONFIG_DEBUG_FS
185-
drmm_mutex_init(&ptdev->base, &ptdev->gems.lock);
185+
ret = drmm_mutex_init(&ptdev->base, &ptdev->gems.lock);
186+
if (ret)
187+
return ret;
188+
186189
INIT_LIST_HEAD(&ptdev->gems.node);
187190
#endif
188191

drivers/gpu/drm/panthor/panthor_fw.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,7 @@ static int panthor_fw_load(struct panthor_device *ptdev)
829829
}
830830

831831
if (hdr.size > iter.size) {
832+
ret = -EINVAL;
832833
drm_err(&ptdev->base, "Firmware image is truncated\n");
833834
goto out;
834835
}

drivers/gpu/drm/ttm/ttm_pool.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,17 +1051,39 @@ long ttm_pool_backup(struct ttm_pool *pool, struct ttm_tt *tt,
10511051
return -EBUSY;
10521052

10531053
#ifdef CONFIG_X86
1054-
/* Anything returned to the system needs to be cached. */
1055-
if (tt->caching != ttm_cached)
1056-
set_pages_array_wb(tt->pages, tt->num_pages);
1054+
/* Anything returned to the system needs to be cached. Walk allocations
1055+
* skipping NULL pages and issue set_pages_array_wb() per contiguous run.
1056+
*/
1057+
if (tt->caching != ttm_cached) {
1058+
pgoff_t run_start = 0, run_count = 0;
1059+
1060+
for (i = 0; i < tt->num_pages; i += num_pages) {
1061+
page = tt->pages[i];
1062+
if (unlikely(!page || ttm_backup_page_ptr_is_handle(page))) {
1063+
if (run_count) {
1064+
set_pages_array_wb(&tt->pages[run_start],
1065+
run_count);
1066+
run_count = 0;
1067+
}
1068+
num_pages = 1;
1069+
continue;
1070+
}
1071+
num_pages = 1UL << ttm_pool_page_order(pool, page);
1072+
if (!run_count)
1073+
run_start = i;
1074+
run_count += num_pages;
1075+
}
1076+
if (run_count)
1077+
set_pages_array_wb(&tt->pages[run_start], run_count);
1078+
}
10571079
#endif
10581080

10591081
if (tt->dma_address || flags->purge) {
10601082
for (i = 0; i < tt->num_pages; i += num_pages) {
10611083
unsigned int order;
10621084

10631085
page = tt->pages[i];
1064-
if (unlikely(!page)) {
1086+
if (unlikely(!page || ttm_backup_page_ptr_is_handle(page))) {
10651087
num_pages = 1;
10661088
continue;
10671089
}
@@ -1104,6 +1126,10 @@ long ttm_pool_backup(struct ttm_pool *pool, struct ttm_tt *tt,
11041126
if (unlikely(!page))
11051127
continue;
11061128

1129+
/* Already-handled entry from a previous attempt. */
1130+
if (unlikely(ttm_backup_page_ptr_is_handle(page)))
1131+
continue;
1132+
11071133
ttm_pool_split_for_swap(pool, page);
11081134

11091135
shandle = ttm_backup_backup_page(backup, page, flags->writeback, i,

drivers/gpu/drm/virtio/virtgpu_gem.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,13 +139,15 @@ void virtio_gpu_gem_object_close(struct drm_gem_object *obj,
139139
if (!vgdev->has_virgl_3d)
140140
return;
141141

142-
objs = virtio_gpu_array_alloc(1);
143-
if (!objs)
144-
return;
145-
virtio_gpu_array_add_obj(objs, obj);
142+
if (vfpriv->context_created) {
143+
objs = virtio_gpu_array_alloc(1);
144+
if (!objs)
145+
return;
146+
virtio_gpu_array_add_obj(objs, obj);
146147

147-
virtio_gpu_cmd_context_detach_resource(vgdev, vfpriv->ctx_id,
148-
objs);
148+
virtio_gpu_cmd_context_detach_resource(vgdev, vfpriv->ctx_id,
149+
objs);
150+
}
149151
virtio_gpu_notify(vgdev);
150152
}
151153

drivers/gpu/drm/virtio/virtgpu_kms.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work)
4949
virtio_gpu_cmd_get_edids(vgdev);
5050
virtio_gpu_cmd_get_display_info(vgdev);
5151
virtio_gpu_notify(vgdev);
52-
drm_helper_hpd_irq_event(vgdev->ddev);
52+
wait_event_timeout(vgdev->resp_wq,
53+
!vgdev->display_info_pending,
54+
5 * HZ);
55+
drm_kms_helper_hotplug_event(vgdev->ddev);
5356
}
5457
events_clear |= VIRTIO_GPU_EVENT_DISPLAY;
5558
}

0 commit comments

Comments
 (0)