Sanity check reloc count in get_reloc_upper_bound
The idea here is the stop tools from allocating up to 32G per section for the arelent pointer array, only to find a little later that the section reloc count was fuzzed. This usually doesn't hurt much (on systems that allow malloc overcommit) except when compiled with asan. We already do this for ELF targets, and while fixing the logic recently I decided other targets ought to do the same. * elf64-sparc.c (elf64_sparc_get_reloc_upper_bound): Sanity check section reloc count against file size. * mach-o.c (bfd_mach_o_get_reloc_upper_bound): Likewise. * aoutx.h (get_reloc_upper_bound): Likewise, and don't duplicate check done in bfd_get_reloc_upper_bound. * pdp11.c (get_reloc_upper_bound): Likewise. * coffgen.c (coff_get_reloc_upper_bound): Likewise.
This commit is contained in:
parent
f735116b3f
commit
a3eb71adfe
20
bfd/aoutx.h
20
bfd/aoutx.h
@ -2485,13 +2485,7 @@ NAME (aout, canonicalize_reloc) (bfd *abfd,
|
||||
long
|
||||
NAME (aout, get_reloc_upper_bound) (bfd *abfd, sec_ptr asect)
|
||||
{
|
||||
bfd_size_type count;
|
||||
|
||||
if (bfd_get_format (abfd) != bfd_object)
|
||||
{
|
||||
bfd_set_error (bfd_error_invalid_operation);
|
||||
return -1;
|
||||
}
|
||||
size_t count, raw;
|
||||
|
||||
if (asect->flags & SEC_CONSTRUCTOR)
|
||||
count = asect->reloc_count;
|
||||
@ -2507,11 +2501,21 @@ NAME (aout, get_reloc_upper_bound) (bfd *abfd, sec_ptr asect)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (count >= LONG_MAX / sizeof (arelent *))
|
||||
if (count >= LONG_MAX / sizeof (arelent *)
|
||||
|| _bfd_mul_overflow (count, obj_reloc_entry_size (abfd), &raw))
|
||||
{
|
||||
bfd_set_error (bfd_error_file_too_big);
|
||||
return -1;
|
||||
}
|
||||
if (!bfd_write_p (abfd))
|
||||
{
|
||||
ufile_ptr filesize = bfd_get_file_size (abfd);
|
||||
if (filesize != 0 && raw > filesize)
|
||||
{
|
||||
bfd_set_error (bfd_error_file_truncated);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return (count + 1) * sizeof (arelent *);
|
||||
}
|
||||
|
||||
|
@ -1976,19 +1976,25 @@ coff_get_normalized_symtab (bfd *abfd)
|
||||
long
|
||||
coff_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
|
||||
{
|
||||
if (bfd_get_format (abfd) != bfd_object)
|
||||
{
|
||||
bfd_set_error (bfd_error_invalid_operation);
|
||||
return -1;
|
||||
}
|
||||
#if SIZEOF_LONG == SIZEOF_INT
|
||||
if (asect->reloc_count >= LONG_MAX / sizeof (arelent *))
|
||||
size_t count, raw;
|
||||
|
||||
count = asect->reloc_count;
|
||||
if (count >= LONG_MAX / sizeof (arelent *)
|
||||
|| _bfd_mul_overflow (count, bfd_coff_relsz (abfd), &raw))
|
||||
{
|
||||
bfd_set_error (bfd_error_file_too_big);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return (asect->reloc_count + 1L) * sizeof (arelent *);
|
||||
if (!bfd_write_p (abfd))
|
||||
{
|
||||
ufile_ptr filesize = bfd_get_file_size (abfd);
|
||||
if (filesize != 0 && raw > filesize)
|
||||
{
|
||||
bfd_set_error (bfd_error_file_truncated);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return (count + 1) * sizeof (arelent *);
|
||||
}
|
||||
|
||||
asymbol *
|
||||
|
@ -37,14 +37,25 @@
|
||||
static long
|
||||
elf64_sparc_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
|
||||
{
|
||||
#if SIZEOF_LONG == SIZEOF_INT
|
||||
if (sec->reloc_count >= LONG_MAX / 2 / sizeof (arelent *))
|
||||
size_t count, raw;
|
||||
|
||||
count = sec->reloc_count;
|
||||
if (count >= LONG_MAX / 2 / sizeof (arelent *)
|
||||
|| _bfd_mul_overflow (count, sizeof (Elf64_External_Rela), &raw))
|
||||
{
|
||||
bfd_set_error (bfd_error_file_too_big);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return (sec->reloc_count * 2L + 1) * sizeof (arelent *);
|
||||
if (!bfd_write_p (abfd))
|
||||
{
|
||||
ufile_ptr filesize = bfd_get_file_size (abfd);
|
||||
if (filesize != 0 && raw > filesize)
|
||||
{
|
||||
bfd_set_error (bfd_error_file_truncated);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return (count * 2 + 1) * sizeof (arelent *);
|
||||
}
|
||||
|
||||
static long
|
||||
|
22
bfd/mach-o.c
22
bfd/mach-o.c
@ -1407,17 +1407,27 @@ bfd_mach_o_write_dyld_info (bfd *abfd, bfd_mach_o_load_command *command)
|
||||
}
|
||||
|
||||
long
|
||||
bfd_mach_o_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED,
|
||||
asection *asect)
|
||||
bfd_mach_o_get_reloc_upper_bound (bfd *abfd, asection *asect)
|
||||
{
|
||||
#if SIZEOF_LONG == SIZEOF_INT
|
||||
if (asect->reloc_count >= LONG_MAX / sizeof (arelent *))
|
||||
size_t count, raw;
|
||||
|
||||
count = asect->reloc_count;
|
||||
if (count >= LONG_MAX / sizeof (arelent *)
|
||||
|| _bfd_mul_overflow (count, BFD_MACH_O_RELENT_SIZE, &raw))
|
||||
{
|
||||
bfd_set_error (bfd_error_file_too_big);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return (asect->reloc_count + 1L) * sizeof (arelent *);
|
||||
if (!bfd_write_p (abfd))
|
||||
{
|
||||
ufile_ptr filesize = bfd_get_file_size (abfd);
|
||||
if (filesize != 0 && raw > filesize)
|
||||
{
|
||||
bfd_set_error (bfd_error_file_truncated);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return (count + 1) * sizeof (arelent *);
|
||||
}
|
||||
|
||||
/* In addition to the need to byte-swap the symbol number, the bit positions
|
||||
|
20
bfd/pdp11.c
20
bfd/pdp11.c
@ -2125,13 +2125,7 @@ NAME (aout, canonicalize_reloc) (bfd *abfd,
|
||||
long
|
||||
NAME (aout, get_reloc_upper_bound) (bfd *abfd, sec_ptr asect)
|
||||
{
|
||||
bfd_size_type count;
|
||||
|
||||
if (bfd_get_format (abfd) != bfd_object)
|
||||
{
|
||||
bfd_set_error (bfd_error_invalid_operation);
|
||||
return -1;
|
||||
}
|
||||
size_t count, raw;
|
||||
|
||||
if (asect->flags & SEC_CONSTRUCTOR)
|
||||
count = asect->reloc_count;
|
||||
@ -2147,11 +2141,21 @@ NAME (aout, get_reloc_upper_bound) (bfd *abfd, sec_ptr asect)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (count >= LONG_MAX / sizeof (arelent *))
|
||||
if (count >= LONG_MAX / sizeof (arelent *)
|
||||
|| _bfd_mul_overflow (count, obj_reloc_entry_size (abfd), &raw))
|
||||
{
|
||||
bfd_set_error (bfd_error_file_too_big);
|
||||
return -1;
|
||||
}
|
||||
if (!bfd_write_p (abfd))
|
||||
{
|
||||
ufile_ptr filesize = bfd_get_file_size (abfd);
|
||||
if (filesize != 0 && raw > filesize)
|
||||
{
|
||||
bfd_set_error (bfd_error_file_truncated);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return (count + 1) * sizeof (arelent *);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user