DF-1389 / fix.diff
diff --git a/sys/dev/drm/i915/intel_bios.c b/sys/dev/drm/i915/intel_bios.c --- a/sys/dev/drm/i915/intel_bios.c +++ b/sys/dev/drm/i915/intel_bios.c @@ -166,12 +166,27 @@ * entry to get the DVO timing entry */ + u16 data_size; + size_t want; int lfp_data_size = lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset - lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset; int dvo_timing_offset = lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset - lvds_lfp_data_ptrs->ptr[0].fp_timing_offset; + + /* Mirror the bounds check already done by sibling fn + * get_lvds_fp_timing(). The BDB section size lives in a u16 + * header just before the section data. Without this, attacker- + * controlled ptr offsets let lfp_data_size / dvo_timing_offset + * address bytes past the section. */ + data_size = ((const u16 *)lvds_lfp_data)[-1]; + want = (size_t)lfp_data_size * (size_t)index + (size_t)dvo_timing_offset; + if (lfp_data_size <= 0 || dvo_timing_offset < 0 || + want > data_size || + want + sizeof(struct lvds_dvo_timing) > data_size) + return NULL; + char *entry = (char *)lvds_lfp_data->data + lfp_data_size * index; return (struct lvds_dvo_timing *)(entry + dvo_timing_offset); |