--- a/sys/dev/drm/radeon/radeon_cs.c +++ b/sys/dev/drm/radeon/radeon_cs.c @@ -270,6 +270,15 @@ u32 ring = RADEON_CS_RING_GFX; s32 priority = 0; + /* Sanity limit: a CS submission has at most a handful of chunks + * (ib, const ib, relocs, flags). Anything beyond this is either + * hostile or broken, and the unchecked allocations below turn + * oversized requests into panics or eternal vm_wait() loops on + * DragonFly (GFP_KERNEL == M_WAITOK without M_NULLOK). + */ + if (cs->num_chunks > 64) + return -EINVAL; + INIT_LIST_HEAD(&p->validated); if (!cs->num_chunks) { @@ -333,6 +342,9 @@ } size = p->chunks[i].length_dw; + /* Bound each chunk's kernel copy too (same rationale). */ + if (size > 1024 * 1024) + return -EINVAL; cdata = (void __user *)(unsigned long)user_chunk.chunk_data; p->chunks[i].user_ptr = cdata; if (user_chunk.chunk_id == RADEON_CHUNK_ID_CONST_IB) @@ -444,8 +456,10 @@ kfree(parser->track); kvfree(parser->relocs); kvfree(parser->vm_bos); - for (i = 0; i < parser->nchunks; i++) - kvfree(parser->chunks[i].kdata); + if (parser->chunks != NULL) { + for (i = 0; i < parser->nchunks; i++) + kvfree(parser->chunks[i].kdata); + } kfree(parser->chunks); kfree(parser->chunks_array); radeon_ib_free(parser->rdev, &parser->ib);