summaryrefslogtreecommitdiffstats
path: root/libelf
diff options
context:
space:
mode:
Diffstat (limited to 'libelf')
-rw-r--r--libelf/ChangeLog20
-rw-r--r--libelf/Makefile.am13
-rw-r--r--libelf/elf32_updatefile.c36
-rw-r--r--libelf/elf_begin.c22
-rw-r--r--libelf/note_xlate.h4
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. */