DF-1470 / fix.diff
diff --git a/sys/dev/drm/amd/powerplay/hwmgr/processpptables.c b/sys/dev/drm/amd/powerplay/hwmgr/processpptables.c --- a/sys/dev/drm/amd/powerplay/hwmgr/processpptables.c +++ b/sys/dev/drm/amd/powerplay/hwmgr/processpptables.c @@ -45,6 +45,22 @@ #define NUM_BITS_CLOCK_INFO_ARRAY_INDEX 6 +/* DF-1470: VBIOS USHORT offsets are added to the powerplay_table base pointer + * and dereferenced as typed struct pointers throughout this file with no check + * that the offset lies within [0, soft_pp_table_size). Validate every offset + * before deref. */ +static bool pp_offset_in_table(struct pp_hwmgr *hwmgr, + const void *base, uint16_t offset, size_t need) +{ + unsigned long start = (unsigned long)base + offset; + unsigned long end = start + need; + unsigned long table_end = (unsigned long)hwmgr->soft_pp_table + + hwmgr->soft_pp_table_size; + + return (offset > 0 && start >= (unsigned long)hwmgr->soft_pp_table && + end <= table_end); +} + static uint16_t get_vce_table_offset(struct pp_hwmgr *hwmgr, const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) { @@ -56,6 +72,10 @@ (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; if (powerplay_table3->usExtendendedHeaderOffset > 0) { + if (!pp_offset_in_table(hwmgr, powerplay_table3, + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset), + sizeof(ATOM_PPLIB_EXTENDEDHEADER))) + return 0; const ATOM_PPLIB_EXTENDEDHEADER *extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *) (((unsigned long)powerplay_table3) + |