diff options
author | Alan Modra <amodra@gmail.com> | 2024-04-04 07:51:47 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2024-04-04 10:30:47 +1030 |
commit | b86d3af60ffc5a821aa54404f57ffe9476919135 (patch) | |
tree | 010ccc4bb1db97e6a77203a1725fa43fd03d6d7d /bfd/aoutx.h | |
parent | 7e217ee2c06e6580386eccba812f767e20e61a00 (diff) | |
download | gdb-b86d3af60ffc5a821aa54404f57ffe9476919135.zip gdb-b86d3af60ffc5a821aa54404f57ffe9476919135.tar.gz gdb-b86d3af60ffc5a821aa54404f57ffe9476919135.tar.bz2 |
USE_MMAP fuzzed object file attacks
If mmap is used without sanity checking, then we'll get a SIGBUS if
an access is done to the mmap'd memory corresponding to a page past
end of file.
* aoutx.h (aout_get_external_symbols): Check that mmap regions
are within file contents. Catch stringsize overflow.
(some_aout_object_p): Don't clear already zeroed fields. Tidy.
* pdp11.c: As for aoutx.h. Copy some fixes too.
Diffstat (limited to 'bfd/aoutx.h')
-rw-r--r-- | bfd/aoutx.h | 65 |
1 files changed, 34 insertions, 31 deletions
diff --git a/bfd/aoutx.h b/bfd/aoutx.h index c8aaa14..fb6326d 100644 --- a/bfd/aoutx.h +++ b/bfd/aoutx.h @@ -498,9 +498,9 @@ NAME (aout, some_aout_object_p) (bfd *abfd, { struct aout_data_struct *rawptr, *oldrawptr; bfd_cleanup result; - size_t amt = sizeof (* rawptr); + size_t amt = sizeof (*rawptr); - rawptr = (struct aout_data_struct *) bfd_zalloc (abfd, amt); + rawptr = bfd_zalloc (abfd, amt); if (rawptr == NULL) return NULL; @@ -551,7 +551,6 @@ NAME (aout, some_aout_object_p) (bfd *abfd, abfd->start_address = execp->a_entry; - obj_aout_symbols (abfd) = NULL; abfd->symcount = execp->a_syms / sizeof (struct external_nlist); /* The default relocation entry size is that of traditional V7 Unix. */ @@ -564,9 +563,6 @@ NAME (aout, some_aout_object_p) (bfd *abfd, bfd_init_window (&obj_aout_sym_window (abfd)); bfd_init_window (&obj_aout_string_window (abfd)); #endif - obj_aout_external_syms (abfd) = NULL; - obj_aout_external_strings (abfd) = NULL; - obj_aout_sym_hashes (abfd) = NULL; if (! NAME (aout, make_sections) (abfd)) goto error_ret; @@ -594,7 +590,6 @@ NAME (aout, some_aout_object_p) (bfd *abfd, /* Call back to the format-dependent code to fill in the rest of the fields and do any further cleanup. Things that should be filled in by the callback: */ - struct exec *execp = exec_hdr (abfd); obj_textsec (abfd)->size = N_TXTSIZE (execp); @@ -618,18 +613,13 @@ NAME (aout, some_aout_object_p) (bfd *abfd, obj_sym_filepos (abfd) = N_SYMOFF (execp); /* Determine the architecture and machine type of the object file. */ - switch (N_MACHTYPE (exec_hdr (abfd))) - { - default: - abfd->obj_arch = bfd_arch_obscure; - break; - } + abfd->obj_arch = bfd_arch_obscure; adata (abfd)->page_size = TARGET_PAGE_SIZE; adata (abfd)->segment_size = SEGMENT_SIZE; adata (abfd)->exec_bytes_size = EXEC_BYTES_SIZE; - return _bfd_no_cleanup + return _bfd_no_cleanup; /* The architecture is encoded in various ways in various a.out variants, or is not encoded at all in some of them. The relocation size depends @@ -639,7 +629,7 @@ NAME (aout, some_aout_object_p) (bfd *abfd, Formats such as b.out, which have additional fields in the a.out header, should cope with them in this callback as well. */ -#endif /* DOCUMENTATION */ +#endif /* DOCUMENTATION */ result = (*callback_to_real_object_p) (abfd); @@ -1311,30 +1301,41 @@ NAME (aout, set_section_contents) (bfd *abfd, static bool aout_get_external_symbols (bfd *abfd) { +#ifdef USE_MMAP + ufile_ptr filesize = bfd_get_file_size (abfd); +#endif + if (obj_aout_external_syms (abfd) == NULL) { bfd_size_type count; - struct external_nlist *syms; + struct external_nlist *syms = NULL; bfd_size_type amt = exec_hdr (abfd)->a_syms; count = amt / EXTERNAL_NLIST_SIZE; if (count == 0) - return true; /* Nothing to do. */ + return true; #ifdef USE_MMAP - if (! bfd_get_file_window (abfd, obj_sym_filepos (abfd), amt, - &obj_aout_sym_window (abfd), true)) - return false; - syms = (struct external_nlist *) obj_aout_sym_window (abfd).data; + if (filesize >= (ufile_ptr) obj_sym_filepos (abfd) + && filesize - obj_sym_filepos (abfd) >= amt) + { + if (! bfd_get_file_window (abfd, obj_sym_filepos (abfd), amt, + &obj_aout_sym_window (abfd), true)) + return false; + syms = (struct external_nlist *) obj_aout_sym_window (abfd).data; + } + else #else - /* We allocate using malloc to make the values easy to free - later on. If we put them on the objalloc it might not be - possible to free them. */ - if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0) - return false; - syms = (struct external_nlist *) _bfd_malloc_and_read (abfd, amt, amt); - if (syms == NULL) - return false; + { + /* We allocate using malloc to make the values easy to free + later on. If we put them on the objalloc it might not be + possible to free them. */ + if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0) + return false; + syms = (struct external_nlist *) _bfd_malloc_and_read (abfd, amt, amt); + if (syms == NULL) + return false; + } #endif obj_aout_external_syms (abfd) = syms; @@ -1356,7 +1357,7 @@ aout_get_external_symbols (bfd *abfd) stringsize = GET_WORD (abfd, string_chars); if (stringsize == 0) stringsize = 1; - else if (stringsize < BYTES_IN_WORD + else if (stringsize + 1 < BYTES_IN_WORD + 1 || (size_t) stringsize != stringsize) { bfd_set_error (bfd_error_bad_value); @@ -1364,7 +1365,9 @@ aout_get_external_symbols (bfd *abfd) } #ifdef USE_MMAP - if (stringsize >= BYTES_IN_WORD) + if (stringsize >= BYTES_IN_WORD + && filesize >= (ufile_ptr) obj_str_filepos (abfd) + && filesize - obj_str_filepos (abfd) >= stringsize + 1) { if (! bfd_get_file_window (abfd, obj_str_filepos (abfd), stringsize + 1, &obj_aout_string_window (abfd), true)) |