Commit ff397be6 authored by Arvind Sankar's avatar Arvind Sankar Committed by Ingo Molnar
Browse files

efi/gop: Fix memory leak in __gop_query32/64()



efi_graphics_output_protocol::query_mode() returns info in
callee-allocated memory which must be freed by the caller, which
we aren't doing.

We don't actually need to call query_mode() in order to obtain the
info for the current graphics mode, which is already there in
gop->mode->info, so just access it directly in the setup_gop32/64()
functions.

Also nothing uses the size of the info structure, so don't update the
passed-in size (which is the size of the gop_handle table in bytes)
unnecessarily.

Signed-off-by: default avatarArvind Sankar <nivedita@alum.mit.edu>
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Bhupesh Sharma <bhsharma@redhat.com>
Cc: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
Cc: linux-efi@vger.kernel.org
Link: https://lkml.kernel.org/r/20191206165542.31469-5-ardb@kernel.org


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent dbd89c30
Loading
Loading
Loading
Loading
+12 −54
Original line number Diff line number Diff line
@@ -83,30 +83,6 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
	}
}

static efi_status_t
__gop_query32(efi_system_table_t *sys_table_arg,
	      struct efi_graphics_output_protocol_32 *gop32,
	      struct efi_graphics_output_mode_info **info,
	      unsigned long *size, u64 *fb_base)
{
	struct efi_graphics_output_protocol_mode_32 *mode;
	efi_graphics_output_protocol_query_mode query_mode;
	efi_status_t status;
	unsigned long m;

	m = gop32->mode;
	mode = (struct efi_graphics_output_protocol_mode_32 *)m;
	query_mode = (void *)(unsigned long)gop32->query_mode;

	status = __efi_call_early(query_mode, (void *)gop32, mode->mode, size,
				  info);
	if (status != EFI_SUCCESS)
		return status;

	*fb_base = mode->frame_buffer_base;
	return status;
}

static efi_status_t
setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
            efi_guid_t *proto, unsigned long size, void **gop_handle)
@@ -128,6 +104,7 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,

	nr_gops = size / sizeof(u32);
	for (i = 0; i < nr_gops; i++) {
		struct efi_graphics_output_protocol_mode_32 *mode;
		struct efi_graphics_output_mode_info *info = NULL;
		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
		bool conout_found = false;
@@ -145,9 +122,11 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
		if (status == EFI_SUCCESS)
			conout_found = true;

		status = __gop_query32(sys_table_arg, gop32, &info, &size,
				       &current_fb_base);
		if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
		mode = (void *)(unsigned long)gop32->mode;
		info = (void *)(unsigned long)mode->info;
		current_fb_base = mode->frame_buffer_base;

		if ((!first_gop || conout_found) &&
		    info->pixel_format != PIXEL_BLT_ONLY) {
			/*
			 * Systems that use the UEFI Console Splitter may
@@ -201,30 +180,6 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
	return EFI_SUCCESS;
}

static efi_status_t
__gop_query64(efi_system_table_t *sys_table_arg,
	      struct efi_graphics_output_protocol_64 *gop64,
	      struct efi_graphics_output_mode_info **info,
	      unsigned long *size, u64 *fb_base)
{
	struct efi_graphics_output_protocol_mode_64 *mode;
	efi_graphics_output_protocol_query_mode query_mode;
	efi_status_t status;
	unsigned long m;

	m = gop64->mode;
	mode = (struct efi_graphics_output_protocol_mode_64 *)m;
	query_mode = (void *)(unsigned long)gop64->query_mode;

	status = __efi_call_early(query_mode, (void *)gop64, mode->mode, size,
				  info);
	if (status != EFI_SUCCESS)
		return status;

	*fb_base = mode->frame_buffer_base;
	return status;
}

static efi_status_t
setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
	    efi_guid_t *proto, unsigned long size, void **gop_handle)
@@ -246,6 +201,7 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,

	nr_gops = size / sizeof(u64);
	for (i = 0; i < nr_gops; i++) {
		struct efi_graphics_output_protocol_mode_64 *mode;
		struct efi_graphics_output_mode_info *info = NULL;
		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
		bool conout_found = false;
@@ -263,9 +219,11 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
		if (status == EFI_SUCCESS)
			conout_found = true;

		status = __gop_query64(sys_table_arg, gop64, &info, &size,
				       &current_fb_base);
		if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
		mode = (void *)(unsigned long)gop64->mode;
		info = (void *)(unsigned long)mode->info;
		current_fb_base = mode->frame_buffer_base;

		if ((!first_gop || conout_found) &&
		    info->pixel_format != PIXEL_BLT_ONLY) {
			/*
			 * Systems that use the UEFI Console Splitter may