DF-3993 / fix.diff
fix for DF-3993: NULL asic->ring[] slot deref via user-selected UVD/VCE CS ring Root cause (two layers): 1) radeon_cs_get_ring() maps RADEON_CS_RING_UVD/VCE to ring indices for every asic family, although the per-family dispatch tables in radeon_asic.c only wire those rings on TN/SI/CI/KV (VCE) resp. RV610+ (UVD); 2) radeon_cs_parser_init() dereferences asic->ring[p->ring]->cs_parse / ->ib_parse before checking that the ring slot itself is non-NULL. Fix: gate the UVD/VCE cases by family exactly like the DMA case already does, and defend the deref with an explicit slot-NULL check. Not applied to sys/ (audit tree is read-only); authored against sys/dev/drm/radeon/radeon_cs.c. diff --git a/sys/dev/drm/radeon/radeon_cs.c b/sys/dev/drm/radeon/radeon_cs.c index 1111111..2222222 100644 --- a/sys/dev/drm/radeon/radeon_cs.c +++ b/sys/dev/drm/radeon/cs.c @@ -233,8 +233,16 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority) break; case RADEON_CS_RING_UVD: + /* UVD ring exists on RV610+ only (radeon_asic.c tables) */ + if (p->rdev->family < CHIP_RV610) + return -EINVAL; p->ring = R600_RING_TYPE_UVD_INDEX; break; case RADEON_CS_RING_VCE: + /* VCE rings exist on TN/SI/CI/KV only (radeon_asic.c tables) */ + if (p->rdev->family < CHIP_ARUBA) + return -EINVAL; p->ring = TN_RING_TYPE_VCE1_INDEX; break; } @@ -371,11 +379,17 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) if (radeon_cs_get_ring(p, ring, priority)) return -EINVAL; + /* the ring slot itself may be absent on this asic family */ + if (p->rdev->asic->ring[p->ring] == NULL) { + DRM_ERROR("Ring %d not present on asic!\n", p->ring); + return -EINVAL; + } + /* we only support VM on some SI+ rings */ if ((p->cs_flags & RADEON_CS_USE_VM) == 0) { if (p->rdev->asic->ring[p->ring]->cs_parse == NULL) { DRM_ERROR("Ring %d requires VM!\n", p->ring); return -EINVAL; } } else { - if (p->rdev->asic->ring[p->ring]->ib_parse == NULL) { + if (p->rdev->asic->ring[p->ring]->ib_parse == NULL) { DRM_ERROR("VM not supported on ring %d!\n", p->ring); return -EINVAL; |