DF-4152 / fix.diff
--- a/sys/dev/drm/amd/amdgpu/amdgpu_atombios.c +++ b/sys/dev/drm/amd/amdgpu/amdgpu_atombios.c @@ -291,6 +291,7 @@ bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device * int i, j, k, path_size, device_support; int connector_type; u16 conn_id, connector_object_id; + u8 *table_end; /* DF-4152: end of the declared Object_Header table */ struct amdgpu_i2c_bus_rec ddc_bus; struct amdgpu_router router; struct amdgpu_gpio_rec gpio; @@ -314,6 +315,8 @@ bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device * if (crev < 2) return false; + table_end = (u8 *)ctx->bios + data_offset + size; + obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset); path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *) (ctx->bios + data_offset + @@ -331,11 +334,16 @@ bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device * path_size = 0; for (i = 0; i < path_obj->ucNumOfDispPath; i++) { uint8_t *addr = (uint8_t *) path_obj->asDispPath; ATOM_DISPLAY_OBJECT_PATH *path; + addr += path_size; path = (ATOM_DISPLAY_OBJECT_PATH *) addr; + if ((u8 *)path + sizeof(*path) > table_end) + break; path_size += le16_to_cpu(path->usSize); + if (path_size > size) + break; if (device_support & le16_to_cpu(path->usDeviceTag)) { @@ -390,6 +398,8 @@ bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device * if (le16_to_cpu(path->usGraphicObjIds[j]) == encoder_obj) { ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *) (ctx->bios + data_offset + le16_to_cpu(enc_obj->asObjects[k].usRecordOffset)); + if ((u8 *)record + sizeof(*record) > table_end) + record = NULL; ATOM_ENCODER_CAP_RECORD *cap_record; u16 caps = 0; - while (record->ucRecordSize > 0 && - record->ucRecordType > 0 && - record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) { + while (record && + (u8 *)record + sizeof(*record) <= table_end && + record->ucRecordSize > 0 && + record->ucRecordType > 0 && + record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) { @@ -429,6 +439,9 @@ bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device * ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *router_src_dst_table = (ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *) (ctx->bios + data_offset + le16_to_cpu(router_obj->asObjects[k].usSrcDstTableOffset)); + if ((u8 *)router_src_dst_table + 2 > table_end) + continue; u8 *num_dst_objs = (u8 *) ((u8 *)router_src_dst_table + 1 + (router_src_dst_table->ucNumberOfSrc * 2)); @@ -444,8 +457,10 @@ bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device * } - while (record->ucRecordSize > 0 && - record->ucRecordType > 0 && + while ((u8 *)record + sizeof(*record) <= table_end && + record->ucRecordSize > 0 && + record->ucRecordType > 0 && record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) { @@ -499,6 +514,8 @@ bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device * (ATOM_COMMON_RECORD_HEADER *) (ctx->bios + data_offset + le16_to_cpu(con_obj-> asObjects[j]. usRecordOffset)); + if ((u8 *)record + sizeof(*record) > table_end) + record = NULL; ATOM_I2C_RECORD *i2c_record; ATOM_HPD_INT_RECORD *hpd_record; ATOM_I2C_ID_CONFIG_ACCESS *i2c_config; - while (record->ucRecordSize > 0 && - record->ucRecordType > 0 && + while (record && + (u8 *)record + sizeof(*record) <= table_end && + record->ucRecordSize > 0 && + record->ucRecordType > 0 && record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) { |