Commit b37aa6e6 authored by Aubrey Li's avatar Aubrey Li Committed by Aubrey Li
Browse files

ACPI: PRM: Handle memory allocation and memory remap failure

mainline inclusion
from mainline-v5.16
commit c52ca713
category: feature
bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I6HNB8


CVE: N/A

Intel-SIG: commit c52ca713 ACPI: PRM: Handle memory allocation and
memory remap failure.
ACPI Platform Runtime Mechanism feature backport.

--------------------------------

Handle memory allocation and memory remap failure in acpi_parse_prmt()
when system runs out of memory to avoid the potential NULL pointer
dereference errors.

Signed-off-by: default avatarAubrey Li <aubrey.li@linux.intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: default avatarAubrey Li <aubrey.li@linux.intel.com>
parent 1f254d79
Loading
Loading
Loading
Loading
+26 −5
Original line number Diff line number Diff line
@@ -96,7 +96,7 @@ acpi_parse_prmt(union acpi_subtable_headers *header, const unsigned long end)
	struct acpi_prmt_handler_info *handler_info;
	struct prm_handler_info *th;
	struct prm_module_info *tm;
	u64 mmio_count = 0;
	u64 *mmio_count;
	u64 cur_handler = 0;
	u32 module_info_size = 0;
	u64 mmio_range_size = 0;
@@ -105,6 +105,8 @@ acpi_parse_prmt(union acpi_subtable_headers *header, const unsigned long end)
	module_info = (struct acpi_prmt_module_info *) header;
	module_info_size = struct_size(tm, handlers, module_info->handler_info_count);
	tm = kmalloc(module_info_size, GFP_KERNEL);
	if (!tm)
		goto parse_prmt_out1;

	guid_copy(&tm->guid, (guid_t *) module_info->module_guid);
	tm->major_rev = module_info->major_rev;
@@ -117,14 +119,24 @@ acpi_parse_prmt(union acpi_subtable_headers *header, const unsigned long end)
		 * Each module is associated with a list of addr
		 * ranges that it can use during the service
		 */
		mmio_count = *(u64 *) memremap(module_info->mmio_list_pointer, 8, MEMREMAP_WB);
		mmio_range_size = struct_size(tm->mmio_info, addr_ranges, mmio_count);
		mmio_count = (u64 *) memremap(module_info->mmio_list_pointer, 8, MEMREMAP_WB);
		if (!mmio_count)
			goto parse_prmt_out2;

		mmio_range_size = struct_size(tm->mmio_info, addr_ranges, *mmio_count);
		tm->mmio_info = kmalloc(mmio_range_size, GFP_KERNEL);
		if (!tm->mmio_info)
			goto parse_prmt_out3;

		temp_mmio = memremap(module_info->mmio_list_pointer, mmio_range_size, MEMREMAP_WB);
		if (!temp_mmio)
			goto parse_prmt_out4;
		memmove(tm->mmio_info, temp_mmio, mmio_range_size);
	} else {
		mmio_range_size = struct_size(tm->mmio_info, addr_ranges, mmio_count);
		tm->mmio_info = kmalloc(mmio_range_size, GFP_KERNEL);
		tm->mmio_info = kmalloc(sizeof(*tm->mmio_info), GFP_KERNEL);
		if (!tm->mmio_info)
			goto parse_prmt_out2;

		tm->mmio_info->mmio_count = 0;
	}

@@ -142,6 +154,15 @@ acpi_parse_prmt(union acpi_subtable_headers *header, const unsigned long end)
	} while (++cur_handler < tm->handler_count && (handler_info = get_next_handler(handler_info)));

	return 0;

parse_prmt_out4:
	kfree(tm->mmio_info);
parse_prmt_out3:
	memunmap(mmio_count);
parse_prmt_out2:
	kfree(tm);
parse_prmt_out1:
	return -ENOMEM;
}

#define GET_MODULE	0