⬢ DragonFlyBSD Kernel Audit
DF-4152 / fix.diff
← back to finding ↓ download raw
--- 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) {