DF-4567 / fix.diff
diff --git a/sys/dev/drm/i915/intel_guc_ct.c b/sys/dev/drm/i915/intel_guc_ct.c index 1278f33d..8c64a5cc 100644 --- a/sys/dev/drm/i915/intel_guc_ct.c +++ b/sys/dev/drm/i915/intel_guc_ct.c @@ -321,18 +321,24 @@ static int ctb_write(struct intel_guc_ct_buffer *ctb, bool want_response) { struct guc_ct_buffer_desc *desc = ctb->desc; + u32 size = PAGE_SIZE / 4; /* in dwords, fixed by allocation */ u32 head = desc->head / 4; /* in dwords */ u32 tail = desc->tail / 4; /* in dwords */ - u32 size = desc->size / 4; /* in dwords */ u32 used; /* in dwords */ u32 header; u32 *cmds = ctb->cmds; unsigned int i; - GEM_BUG_ON(desc->size % 4); - GEM_BUG_ON(desc->head % 4); - GEM_BUG_ON(desc->tail % 4); - GEM_BUG_ON(tail >= size); + /* + * The descriptor lives in memory shared with the GuC firmware and + * its fields are firmware-writable. GEM_BUG_ON() is compiled out + * in production builds, so validate for real before any divide or + * ring arithmetic (desc->size == 0 would panic on % size below). + */ + if (unlikely(desc->size != size * 4) || + unlikely(desc->head % 4) || unlikely(head >= size) || + unlikely(desc->tail % 4) || unlikely(tail >= size)) + return -EPROTO; /* * tail == head condition indicates empty. GuC FW does not support @@ -579,19 +585,19 @@ static inline bool ct_header_is_response(u32 header) static int ctb_read(struct intel_guc_ct_buffer *ctb, u32 *data) { struct guc_ct_buffer_desc *desc = ctb->desc; + u32 size = PAGE_SIZE / 4; /* in dwords, fixed by allocation */ u32 head = desc->head / 4; /* in dwords */ u32 tail = desc->tail / 4; /* in dwords */ - u32 size = desc->size / 4; /* in dwords */ u32 *cmds = ctb->cmds; s32 available; /* in dwords */ unsigned int len; unsigned int i; - GEM_BUG_ON(desc->size % 4); - GEM_BUG_ON(desc->head % 4); - GEM_BUG_ON(desc->tail % 4); - GEM_BUG_ON(tail >= size); - GEM_BUG_ON(head >= size); + /* As in ctb_write(): the descriptor is firmware-writable. */ + if (unlikely(desc->size != size * 4) || + unlikely(desc->head % 4) || unlikely(head >= size) || + unlikely(desc->tail % 4) || unlikely(tail >= size)) + return -EPROTO; /* tail == head condition indicates empty */ available = tail - head; |