diff options
Diffstat (limited to 'libelf')
| -rw-r--r-- | libelf/ChangeLog | 20 | ||||
| -rw-r--r-- | libelf/Makefile.am | 13 | ||||
| -rw-r--r-- | libelf/elf32_updatefile.c | 36 | ||||
| -rw-r--r-- | libelf/elf_begin.c | 22 | ||||
| -rw-r--r-- | libelf/note_xlate.h | 4 |
5 files changed, 81 insertions, 14 deletions
diff --git a/libelf/ChangeLog b/libelf/ChangeLog index 68c4fbdd..d8e8fdc8 100644 --- a/libelf/ChangeLog +++ b/libelf/ChangeLog @@ -1,3 +1,23 @@ +2019-02-14 Mark Wielaard <[email protected]> + + * elf_begin.c (read_long_names): Make sure ar_size is properly + terminated. Sanity check len early if we can. + +2019-01-18 Mark Wielaard <[email protected]> + + * Makefile.am (INSTALL_ELFH): Add elf.h to include_HEADERS when + defined, otherwise (the default) add elf.h to noinst_HEADERS. + +2019-01-16 Mark Wielaard <[email protected]> + + * note_xlate.h (elf_cvt_note): Check n_namesz and n_descsz don't + overflow note_len into note header. + +2018-11-17 Mark Wielaard <[email protected]> + + * elf32_updatefile.c (updatemmap): Make sure to call convert + function on a properly aligned destination. + 2018-11-16 Mark Wielaard <[email protected]> * libebl.h (__elf32_msize): Mark with const attribute. diff --git a/libelf/Makefile.am b/libelf/Makefile.am index ba4e3ebf..0d8679f2 100644 --- a/libelf/Makefile.am +++ b/libelf/Makefile.am @@ -39,6 +39,16 @@ noinst_LIBRARIES = libelf_pic.a noinst_PROGRAMS = $(noinst_LIBRARIES:_pic.a=.so) include_HEADERS = libelf.h gelf.h nlist.h +noinst_HEADERS = abstract.h common.h exttypes.h gelf_xlate.h libelfP.h \ + version_xlate.h gnuhash_xlate.h note_xlate.h dl-hash.h \ + chdr_xlate.h + +if INSTALL_ELFH +include_HEADERS += elf.h +else +noinst_HEADERS += elf.h +endif + pkginclude_HEADERS = elf-knowledge.h libelf_a_CFLAGS = -fPIC -fvisibility=hidden $(AM_CFLAGS) @@ -124,9 +134,6 @@ uninstall: uninstall-am rm -f $(DESTDIR)$(libdir)/libelf.so.$(VERSION) rm -f $(DESTDIR)$(libdir)/libelf.so -noinst_HEADERS = elf.h abstract.h common.h exttypes.h gelf_xlate.h libelfP.h \ - version_xlate.h gnuhash_xlate.h note_xlate.h dl-hash.h \ - chdr_xlate.h EXTRA_DIST = libelf.map CLEANFILES += $(am_libelf_pic_a_OBJECTS) libelf.so.$(VERSION) diff --git a/libelf/elf32_updatefile.c b/libelf/elf32_updatefile.c index f2e9a288..284bacc9 100644 --- a/libelf/elf32_updatefile.c +++ b/libelf/elf32_updatefile.c @@ -1,5 +1,5 @@ /* Write changed data structures. - Copyright (C) 2000-2010, 2014, 2015, 2016 Red Hat, Inc. + Copyright (C) 2000-2010, 2014, 2015, 2016, 2018 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper <[email protected]>, 2000. @@ -354,7 +354,9 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum) user's section data with the latest one, rather than crashing. */ - if (unlikely (change_bo)) + if (unlikely (change_bo + && dl->data.d.d_size != 0 + && dl->data.d.d_type != ELF_T_BYTE)) { #if EV_NUM != 2 xfct_t fctp; @@ -364,9 +366,33 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum) # define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type] #endif - /* Do the real work. */ - (*fctp) (last_position, dl->data.d.d_buf, - dl->data.d.d_size, 1); + size_t align; + align = __libelf_type_align (ELFW(ELFCLASS,LIBELFBITS), + dl->data.d.d_type); + if ((((uintptr_t) last_position) + & (uintptr_t) (align - 1)) == 0) + { + /* No need to copy, we can convert directly. */ + (*fctp) (last_position, dl->data.d.d_buf, + dl->data.d.d_size, 1); + } + else + { + /* We have to do the conversion on properly + aligned memory first. */ + size_t size = dl->data.d.d_size; + char *converted = aligned_alloc (align, size); + if (converted == NULL) + { + __libelf_seterrno (ELF_E_NOMEM); + return 1; + } + (*fctp) (converted, dl->data.d.d_buf, size, 1); + + /* And then write it to the mmapped file. */ + memcpy (last_position, converted, size); + free (converted); + } last_position += dl->data.d.d_size; } diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c index b20ab4f3..fde14c61 100644 --- a/libelf/elf_begin.c +++ b/libelf/elf_begin.c @@ -736,7 +736,17 @@ read_long_names (Elf *elf) hdr = &hdrm; } - len = atol (hdr->ar_size); + /* The ar_size is given as a fixed size decimal string, right + padded with spaces. Make sure we read it properly even if + there is no terminating space. */ + char buf[sizeof (hdr->ar_size) + 1]; + const char *string = hdr->ar_size; + if (hdr->ar_size[sizeof (hdr->ar_size) - 1] != ' ') + { + *((char *) mempcpy (buf, hdr->ar_size, sizeof (hdr->ar_size))) = '\0'; + string = buf; + } + len = atol (string); if (memcmp (hdr->ar_name, "// ", 16) == 0) break; @@ -744,6 +754,13 @@ read_long_names (Elf *elf) offset += sizeof (struct ar_hdr) + ((len + 1) & ~1l); } + /* Sanity check len early if we can. */ + if (elf->map_address != NULL) + { + if (len > elf->maximum_size - offset - sizeof (struct ar_hdr)) + return NULL; + } + /* Due to the stupid format of the long name table entry (which are not NUL terminted) we have to provide an appropriate representation anyhow. Therefore we always make a copy which has the appropriate form. */ @@ -754,8 +771,6 @@ read_long_names (Elf *elf) if (elf->map_address != NULL) { - if (len > elf->maximum_size - offset - sizeof (struct ar_hdr)) - goto too_much; /* Simply copy it over. */ elf->state.ar.long_names = (char *) memcpy (newp, elf->map_address + offset @@ -769,7 +784,6 @@ read_long_names (Elf *elf) + sizeof (struct ar_hdr)) != len)) { - too_much: /* We were not able to read all data. */ free (newp); elf->state.ar.long_names = NULL; diff --git a/libelf/note_xlate.h b/libelf/note_xlate.h index 9bdc3e2c..bc9950ff 100644 --- a/libelf/note_xlate.h +++ b/libelf/note_xlate.h @@ -46,13 +46,13 @@ elf_cvt_note (void *dest, const void *src, size_t len, int encode, /* desc needs to be aligned. */ note_len += n->n_namesz; note_len = nhdr8 ? NOTE_ALIGN8 (note_len) : NOTE_ALIGN4 (note_len); - if (note_len > len || note_len < 8) + if (note_len > len || note_len < sizeof *n) break; /* data as a whole needs to be aligned. */ note_len += n->n_descsz; note_len = nhdr8 ? NOTE_ALIGN8 (note_len) : NOTE_ALIGN4 (note_len); - if (note_len > len || note_len < 8) + if (note_len > len || note_len < sizeof *n) break; /* Copy or skip the note data. */ |
