* grub-core/loader/i386/linux.c (grub_linux_boot): Fix overflow and

uninited variable. Allocate at least setup_sects.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2012-05-31 12:04:55 +02:00
parent a4e5ca80d9
commit f19cb95e1d
2 changed files with 36 additions and 22 deletions

View file

@ -1,3 +1,8 @@
2012-05-31 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/loader/i386/linux.c (grub_linux_boot): Fix overflow and
uninited variable. Allocate at least setup_sects.
2012-05-30 Vladimir Serbinenko <phcoder@gmail.com> 2012-05-30 Vladimir Serbinenko <phcoder@gmail.com>
Fix handling of EFI with big memory maps. Fix handling of EFI with big memory maps.

View file

@ -379,13 +379,16 @@ grub_linux_boot (void)
char *tmp; char *tmp;
struct grub_relocator32_state state; struct grub_relocator32_state state;
void *real_mode_mem; void *real_mode_mem;
grub_addr_t real_mode_target; grub_addr_t real_mode_target = 0;
grub_size_t real_size, mmap_size; grub_size_t real_size, mmap_size;
grub_size_t cl_offset; grub_size_t cl_offset;
mmap_size = find_mmap_size (); mmap_size = find_mmap_size ();
/* Make sure that each size is aligned to a page boundary. */ /* Make sure that each size is aligned to a page boundary. */
cl_offset = ALIGN_UP (mmap_size + sizeof (*params), 4096); cl_offset = ALIGN_UP (mmap_size + sizeof (*params), 4096);
if (cl_offset < ((grub_size_t) params->setup_sects << GRUB_DISK_SECTOR_BITS))
cl_offset = ALIGN_UP ((grub_size_t) (params->setup_sects
<< GRUB_DISK_SECTOR_BITS), 4096);
real_size = ALIGN_UP (cl_offset + maximal_cmdline_size, 4096); real_size = ALIGN_UP (cl_offset + maximal_cmdline_size, 4096);
#ifdef GRUB_MACHINE_EFI #ifdef GRUB_MACHINE_EFI
@ -403,27 +406,30 @@ grub_linux_boot (void)
grub_memory_type_t type) grub_memory_type_t type)
{ {
/* We must put real mode code in the traditional space. */ /* We must put real mode code in the traditional space. */
if (type != GRUB_MEMORY_AVAILABLE || addr > 0x90000)
return 0;
if (type == GRUB_MEMORY_AVAILABLE if (addr + size < 0x10000)
&& addr <= 0x90000) return 0;
if (addr < 0x10000)
{ {
if (addr < 0x10000) size += addr - 0x10000;
{ addr = 0x10000;
size += addr - 0x10000;
addr = 0x10000;
}
if (addr + size > 0x90000)
size = 0x90000 - addr;
if (real_size + efi_mmap_size > size)
return 0;
real_mode_target = ((addr + size) - (real_size + efi_mmap_size));
return 1;
} }
return 0; if (addr + size > 0x90000)
size = 0x90000 - addr;
if (real_size + efi_mmap_size > size)
return 0;
grub_dprintf ("linux", "addr = %lx, size = %x, need_size = %x\n",
(unsigned long) addr,
(unsigned) size,
(unsigned) (real_size + efi_mmap_size));
real_mode_target = ((addr + size) - (real_size + efi_mmap_size));
return 1;
} }
#ifdef GRUB_MACHINE_EFI #ifdef GRUB_MACHINE_EFI
grub_efi_mmap_iterate (hook, 1); grub_efi_mmap_iterate (hook, 1);
@ -432,6 +438,11 @@ grub_linux_boot (void)
#else #else
grub_mmap_iterate (hook); grub_mmap_iterate (hook);
#endif #endif
grub_dprintf ("linux", "real_mode_target = %lx, real_size = %x, efi_mmap_size = %x\n",
(unsigned long) real_mode_target,
(unsigned) real_size,
(unsigned) efi_mmap_size);
if (! real_mode_target) if (! real_mode_target)
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages"); return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages");
@ -446,10 +457,8 @@ grub_linux_boot (void)
} }
efi_mmap_buf = (grub_uint8_t *) real_mode_mem + real_size; efi_mmap_buf = (grub_uint8_t *) real_mode_mem + real_size;
grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_target = %lx, real_size = %x\n", grub_dprintf ("linux", "real_mode_mem = %lx\n",
(unsigned long) real_mode_mem, (unsigned long) real_mode_target, (unsigned long) real_mode_mem);
(unsigned) real_size);
params = real_mode_mem; params = real_mode_mem;
*params = linux_params; *params = linux_params;