diff --git a/ChangeLog b/ChangeLog index 6faadecdb..f610f4945 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2013-11-22 Vladimir Serbinenko + + * grub-core/kern/x86_64/dl.c (grub_arch_dl_relocate_symbols): Add + range-checking for 32-bit quantities. + 2013-11-22 Vladimir Serbinenko * configure.ac: Compile with -fPIC when compiling with clang on diff --git a/grub-core/kern/x86_64/dl.c b/grub-core/kern/x86_64/dl.c index 65f09ef53..17c121544 100644 --- a/grub-core/kern/x86_64/dl.c +++ b/grub-core/kern/x86_64/dl.c @@ -100,14 +100,32 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) break; case R_X86_64_PC32: - *addr32 += rel->r_addend + sym->st_value - - (Elf64_Xword) seg->addr - rel->r_offset; + { + grub_int64_t value; + value = ((grub_int32_t) *addr32) + rel->r_addend + sym->st_value - + (Elf64_Xword) seg->addr - rel->r_offset; + if (value != (grub_int32_t) value) + return grub_error (GRUB_ERR_BAD_MODULE, "relocation out of range"); + *addr32 = value; + } break; case R_X86_64_32: + { + grub_uint64_t value = *addr32 + rel->r_addend + sym->st_value; + if (value != (grub_uint32_t) value) + return grub_error (GRUB_ERR_BAD_MODULE, "relocation out of range"); + *addr32 = value; + } + break; case R_X86_64_32S: - *addr32 += rel->r_addend + sym->st_value; - break; + { + grub_int64_t value = ((grub_int32_t) *addr32) + rel->r_addend + sym->st_value; + if (value != (grub_int32_t) value) + return grub_error (GRUB_ERR_BAD_MODULE, "relocation out of range"); + *addr32 = value; + } + break; default: return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,