mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 22:14:03 +02:00
drm/amd/powerplay: fix VoltageObjectInfo zero-stride loop and OOB read
Reject voltage objects whose usSize is smaller than the header or would advance the cursor past the table end, preventing an infinite loop or heap OOB read when the VBIOS supplies a malformed VoltageObjectInfo table. Fixes:c82baa2818("drm/amd/powerplay: add Tonga dpm support (v3)") Fixes:0d2c7569e1("drm/amdgpu: add new atomfirmware based helpers for powerplay") Signed-off-by: Asad Kamal <asad.kamal@amd.com> Reviewed-by: Lijo Lazar <lijo.lazar@amd.com> Reviewed-by: Yang Wang <kevinyang.wang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
6c2abd0ec0
commit
5d3cc8e388
|
|
@ -268,15 +268,21 @@ static const ATOM_VOLTAGE_OBJECT_V3 *atomctrl_lookup_voltage_type_v3(
|
|||
unsigned int offset = offsetof(ATOM_VOLTAGE_OBJECT_INFO_V3_1, asVoltageObj[0]);
|
||||
uint8_t *start = (uint8_t *)voltage_object_info_table;
|
||||
|
||||
while (offset < size) {
|
||||
while (offset + sizeof(ATOM_VOLTAGE_OBJECT_HEADER_V3) <= size) {
|
||||
const ATOM_VOLTAGE_OBJECT_V3 *voltage_object =
|
||||
(const ATOM_VOLTAGE_OBJECT_V3 *)(start + offset);
|
||||
u16 obj_size;
|
||||
|
||||
obj_size = le16_to_cpu(voltage_object->asGpioVoltageObj.sHeader.usSize);
|
||||
if (obj_size < sizeof(voltage_object->asGpioVoltageObj.sHeader) ||
|
||||
offset + obj_size > size)
|
||||
break;
|
||||
|
||||
if (voltage_type == voltage_object->asGpioVoltageObj.sHeader.ucVoltageType &&
|
||||
voltage_mode == voltage_object->asGpioVoltageObj.sHeader.ucVoltageMode)
|
||||
return voltage_object;
|
||||
|
||||
offset += le16_to_cpu(voltage_object->asGpioVoltageObj.sHeader.usSize);
|
||||
offset += obj_size;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -36,16 +36,21 @@ static const union atom_voltage_object_v4 *pp_atomfwctrl_lookup_voltage_type_v4(
|
|||
offsetof(struct atom_voltage_objects_info_v4_1, voltage_object[0]);
|
||||
unsigned long start = (unsigned long)voltage_object_info_table;
|
||||
|
||||
while (offset < size) {
|
||||
while (offset + sizeof(struct atom_voltage_object_header_v4) <= size) {
|
||||
const union atom_voltage_object_v4 *voltage_object =
|
||||
(const union atom_voltage_object_v4 *)(start + offset);
|
||||
u16 obj_size;
|
||||
|
||||
obj_size = le16_to_cpu(voltage_object->gpio_voltage_obj.header.object_size);
|
||||
if (obj_size < sizeof(voltage_object->gpio_voltage_obj.header) ||
|
||||
offset + obj_size > size)
|
||||
break;
|
||||
|
||||
if (voltage_type == voltage_object->gpio_voltage_obj.header.voltage_type &&
|
||||
voltage_mode == voltage_object->gpio_voltage_obj.header.voltage_mode)
|
||||
return voltage_object;
|
||||
|
||||
offset += le16_to_cpu(voltage_object->gpio_voltage_obj.header.object_size);
|
||||
|
||||
offset += obj_size;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user