diff options
author | Matt Fleming <matt.fleming@intel.com> | 2011-08-18 18:44:22 +0100 |
---|---|---|
committer | Matt Fleming <matt.fleming@intel.com> | 2011-08-18 20:55:56 +0100 |
commit | c7615edf9fe977f072f7ea3287884d36343761d2 (patch) | |
tree | d85e697a4154db04a4b111defda273403fe38ad7 | |
parent | a51c96f8d934c02dcf6fdec4e47905584d18f9f1 (diff) | |
download | efilinux-c7615edf9fe977f072f7ea3287884d36343761d2.tar.gz |
bzimage: Fix typecast bug on i386
Before 32-bit support we were playing fast and loose with casts. The
problem was that we were casting away legimate warnings, such as the
compiler telling us that the value it was storing into a variable to
was too big to fit.
emalloc() was a prime example, in various places we passed a pointer
to a pointer as the third argument to emalloc which has type
EFI_PHYSICALL_ADDRESS *, where EFI_PHYSICAL_ADDRESS is a 64-bit type,
like so,
emalloc(UINTN size, UINTN align, EFI_PHYSICAL_ADDRESS *addr)
Then inside emalloc() we do,
*addr = aligned;
On 64-bit this is fine because,
sizeof(void *) == sizeof(EFI_PHYSICAL_ADDRESS)
but if we have a 32-bit pointer we attempt to store a 64-bit value
into a 32-bit data type. This led to stack corruption when we passed
the address of a pointer on the stack to emalloc().
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
-rw-r--r-- | loaders/bzimage/bzimage.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/loaders/bzimage/bzimage.c b/loaders/bzimage/bzimage.c index cab1431..335fc9e 100644 --- a/loaders/bzimage/bzimage.c +++ b/loaders/bzimage/bzimage.c @@ -56,7 +56,7 @@ EFI_STATUS load_kernel(EFI_HANDLE image, CHAR16 *name, char *cmdline) { UINTN map_size, _map_size, map_key; - EFI_PHYSICAL_ADDRESS kernel_start; + EFI_PHYSICAL_ADDRESS kernel_start, addr; struct boot_params *boot_params; EFI_MEMORY_DESCRIPTOR *map_buf; struct e820_entry *e820_map; @@ -155,11 +155,12 @@ load_kernel(EFI_HANDLE image, CHAR16 *name, char *cmdline) goto out; file_size(rdfile, &size); - err = emalloc(size, 1, (EFI_PHYSICAL_ADDRESS *)&rd); + err = emalloc(size, 1, &addr); if (err != EFI_SUCCESS) { file_close(rdfile); goto out; } + rd = (void *)(UINTN)addr; if ((UINT32)(UINT64)rd > buf->hdr.ramdisk_max) { Print(L"ramdisk address is too high!\n"); @@ -204,10 +205,12 @@ load_kernel(EFI_HANDLE image, CHAR16 *name, char *cmdline) * * Max kernel size is 8MB */ - err = emalloc(16384, 1, (EFI_PHYSICAL_ADDRESS *)&boot_params); + err = emalloc(16384, 1, &addr); if (err != EFI_SUCCESS) goto out; + boot_params = (struct boot_params *)(UINTN)addr; + memset((void *)boot_params, 0x0, 16384); /* Copy first two sectors to boot_params */ @@ -252,10 +255,11 @@ load_kernel(EFI_HANDLE image, CHAR16 *name, char *cmdline) again: _map_size = map_size; - err = emalloc(map_size, 1, (EFI_PHYSICAL_ADDRESS *)&map_buf); + err = emalloc(map_size, 1, &addr); if (err != EFI_SUCCESS) goto out; + map_buf = (EFI_MEMORY_DESCRIPTOR *)(UINTN)addr; size = 0x800000; err = emalloc(size, buf->hdr.kernel_alignment, &kernel_start); if (err != EFI_SUCCESS) |