elf_update might crash for 65280+ sections when section zero headers aren't loaded. Make sure section zero is loaded before trying to write to it.
Add testcase to tests/test-manyfuncs.c but use ELF_C_READ_MMAP_PRIVATE to workaround https://sourceware.org/bugzilla/show_bug.cgi?id=33968 * libelf/elf32_updatenull.c (updatenull_wrlock): Call getshdr_wrlock to load shdr. * tests/test-manyfuncs.c (check_elf): Use elf_begin with ELF_C_READ_MMAP_PRIVATE if use_mmap. Call elf_update early. https://sourceware.org/bugzilla/show_bug.cgi?id=33967 Signed-off-by: Mark Wielaard <[email protected]> --- libelf/elf32_updatenull.c | 4 ++++ tests/test-manyfuncs.c | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/libelf/elf32_updatenull.c b/libelf/elf32_updatenull.c index 74c27fdaa7b5..57239ee4ac90 100644 --- a/libelf/elf32_updatenull.c +++ b/libelf/elf32_updatenull.c @@ -184,6 +184,10 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum) of the zeroth section. */ Elf_Scn *scn0 = &elf->state.ELFW(elf,LIBELFBITS).scns.data[0]; + /* Make sure section zero header is actually loaded. */ + if (scn0->shdr.ELFW(e,LIBELFBITS) == NULL) + (void) __elfw2(LIBELFBITS,getshdr_wrlock) (scn0); + update_if_changed (scn0->shdr.ELFW(e,LIBELFBITS)->sh_size, shnum, scn0->shdr_flags); } diff --git a/tests/test-manyfuncs.c b/tests/test-manyfuncs.c index 725690203ff1..3129682d59e4 100644 --- a/tests/test-manyfuncs.c +++ b/tests/test-manyfuncs.c @@ -52,13 +52,26 @@ check_elf (const char *fname, bool use_mmap) exit (1); } - Elf *elf = elf_begin (fd, use_mmap ? ELF_C_READ_MMAP : ELF_C_READ, NULL); + Elf *elf = elf_begin (fd, use_mmap ? ELF_C_READ_MMAP_PRIVATE : ELF_C_READ, + NULL); if (elf == NULL) { printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1)); exit (1); } + /* Check if we can update the elf layout without having read anything. + This used to crash with 65280+ sections. + https://sourceware.org/bugzilla/show_bug.cgi?id=33967 + Still crashes for read-only mmap. + https://sourceware.org/bugzilla/show_bug.cgi?id=33968 + */ + if (elf_update (elf, ELF_C_NULL) < 0) + { + printf ("failure in elf_update: %s\n", elf_errmsg (-1)); + exit (1); + } + /* How many sections are there? */ size_t shnum; if (elf_getshdrnum (elf, &shnum) < 0) -- 2.53.0
