⬢ DragonFlyBSD Kernel Audit
DF-5778 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/drm/amd/display/dc/irq/irq_service.c b/sys/dev/drm/amd/display/dc/irq/irq_service.c
index 000000000000..000000000000 100644
--- a/sys/dev/drm/amd/display/dc/irq/irq_service.c
+++ b/sys/dev/drm/amd/display/dc/irq/irq_service.c
@@ -162,6 +162,11 @@ bool dal_irq_service_ack(
 enum dc_irq_source dal_irq_service_to_irq_source(
 		struct irq_service *irq_service,
 		uint32_t src_id,
 		uint32_t ext_id)
 {
+	if (!irq_service || !irq_service->funcs ||
+			!irq_service->funcs->to_dal_irq_source)
+		return DC_IRQ_SOURCE_INVALID;
+
 	return irq_service->funcs->to_dal_irq_source(
 		irq_service,
 		src_id,
diff --git a/sys/dev/drm/amd/display/dc/core/dc.c b/sys/dev/drm/amd/display/dc/core/dc.c
index 000000000000..000000000000 100644
--- a/sys/dev/drm/amd/display/dc/core/dc.c
+++ b/sys/dev/drm/amd/display/dc/core/dc.c
@@ -1672,12 +1672,22 @@ uint8_t dc_get_current_stream_count(struct dc *dc)
 enum dc_irq_source dc_interrupt_to_irq_source(
 		struct dc *dc,
 		uint32_t src_id,
 		uint32_t ext_id)
 {
+	if (dc == NULL || dc->res_pool == NULL || dc->res_pool->irqs == NULL)
+		return DC_IRQ_SOURCE_INVALID;
+
 	return dal_irq_service_to_irq_source(dc->res_pool->irqs, src_id, ext_id);
 }
 
 bool dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable)
 {
 
 	if (dc == NULL)
 		return false;
 
 	return dal_irq_service_set(dc->res_pool->irqs, src, enable);
 }
 
 void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src)
 {
+	if (dc == NULL || dc->res_pool == NULL || dc->res_pool->irqs == NULL)
+		return;
+
 	dal_irq_service_ack(dc->res_pool->irqs, src);
 }
--
2.11.0

DF-5778: dal_irq_service_to_irq_source() double-dereferences
irq_service->funcs->to_dal_irq_source with no validation, unlike every
sibling entry point in the same file (set/ack validate via
find_irq_source_info; construct/destroy validate their handles), and
unlike dc_interrupt_set() in the wrappers. dal_irq_service_construct()'s
void failure is also swallowed by the family constructors (they wire
info/funcs unconditionally), so a half-initialised service would carry
NULL ctx/funcs into this path. No in-tree caller can produce the NULL
object today (all 8 resource create-sites NULL-check irqs; dc->ctx is
alloc-checked before pool creation), so this is defense-in-depth: guard
the deref and mirror dc_interrupt_set's NULL check in the two wrappers
that lack it. Returning DC_IRQ_SOURCE_INVALID is the established safe
answer (the INVALID table slot is a dummy entry that logs and fails).

Note: index/hash lines are placeholders (audit tree is read-only; diff
authored for review, validated by context, not applied).