[PATCH] libelf: Make sure version xlate dest buffer is fully defined.
by Mark Wielaard
https://bugzilla.redhat.com/show_bug.cgi?id=1170810#c16
contains an example of usage of undefined memory when version section
data needs to be translated, but the version xlate functions detect they
cannot fully transform the section data. To make sure the dest buffer
data is completely defined this patch makes sure all data is moved
from src to dest first. This is somewhat inefficient since normally
all data will be fully converted. But the translation functions have
no way to indicate only partial data was converted.
Reported-by: Alexander Cherepanov <cherepan(a)mccme.ru>
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libelf/ChangeLog | 5 +++++
libelf/version_xlate.h | 12 +++++++++++-
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 2ca9509..adfccf1 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,8 @@
+2015-01-03 Mark Wielaard <mjw(a)redhat.com>
+
+ * version_xlate.h (elf_cvt_Verdef): Use memmove to copy src to dest.
+ (elf_cvt_Verneed): Likewise.
+
2014-12-30 Mark Wielaard <mjw(a)redhat.com>
* elf_getphdrnum.c (__elf_getphdrnum_chk_rdlock): New function.
diff --git a/libelf/version_xlate.h b/libelf/version_xlate.h
index 16eaa19..9fe01c6 100644
--- a/libelf/version_xlate.h
+++ b/libelf/version_xlate.h
@@ -1,5 +1,5 @@
/* Conversion functions for versioning information.
- Copyright (C) 1998, 1999, 2000, 2002, 2003 Red Hat, Inc.
+ Copyright (C) 1998, 1999, 2000, 2002, 2003, 2015 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper(a)redhat.com>, 1998.
@@ -55,6 +55,11 @@ elf_cvt_Verdef (void *dest, const void *src, size_t len, int encode)
if (len == 0)
return;
+ /* Below we rely on the next field offsets to be correct, start by
+ copying over all data as is in case some data isn't translated.
+ We don't want to leave (undefined) garbage in the dest buffer. */
+ memmove (dest, src, len);
+
do
{
size_t aux_offset;
@@ -149,6 +154,11 @@ elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
if (len == 0)
return;
+ /* Below we rely on the next field offsets to be correct, start by
+ copying over all data as is in case some data isn't translated.
+ We don't want to leave (undefined) garbage in the dest buffer. */
+ memmove (dest, src, len);
+
do
{
size_t aux_offset;
--
2.1.0
8 years, 6 months
[PATCH] Fix section corruption bug
by Thilo Schulz
Hi,
When adding data to existing sections in ELF files, libelf may corrupt
those sections, i.e. overwrite the existing data if certain conditions are
met.
If an Elf_Scn structure has seen a call to elf_rawdata(scn) before but no
call to elf_getdata(scn), scn->read_data flag is set, but not
scn->data_list_rear.
Thus, elf_newdata(scn) incorrectly detects a "new user added section" when
really it is a section with live, valid data that will be overwritten by
elf_update(), corrupting the section.
This patch fixes this incorrect behaviour.
Signed-off-by: Thilo Schulz <thilo(a)tjps.eu>
---
libelf/elf_newdata.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libelf/elf_newdata.c b/libelf/elf_newdata.c
index 90d1813..f90eb0a 100644
--- a/libelf/elf_newdata.c
+++ b/libelf/elf_newdata.c
@@ -64,7 +64,7 @@ elf_newdata (Elf_Scn *scn)
rwlock_wrlock (scn->elf->lock);
- if (scn->data_read && scn->data_list_rear == NULL)
+ if (scn->data_read && scn->data_list_rear == NULL && !scn->rawdata.s)
{
/* This means the section was created by the user and this is the
first data. */
--
1.7.10.4
8 years, 8 months
[PATCH] libelf: Make sure string returned by elf_strptr is NUL terminated.
by Mark Wielaard
The result of elf_strptr is often used directly to print or strcmp
the string. If the section data was truncated or corrupted that could
lead to invalid memory reads possibly crashing the application.
https://bugzilla.redhat.com/show_bug.cgi?id=1170810#c24
Reported-by: Alexander Cherepanov <cherepan(a)mccme.ru>
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libelf/ChangeLog | 5 +++++
libelf/elf_strptr.c | 23 +++++++++++++++++++++--
2 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 8bf1256..e290f48 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,8 @@
+2015-01-22 Mark Wielaard <mjw(a)redhat.com>
+
+ * elf_strptr (elf_strptr): Make sure returned string is NUL
+ terminated.
+
2015-01-21 Mark Wielaard <mjw(a)redhat.com>
* elf_strptr.c (elf_strptr): Check data_list_rear == NULL instead
diff --git a/libelf/elf_strptr.c b/libelf/elf_strptr.c
index 62936a0..e73bf36 100644
--- a/libelf/elf_strptr.c
+++ b/libelf/elf_strptr.c
@@ -86,6 +86,7 @@ elf_strptr (elf, idx, offset)
}
}
+ size_t sh_size = 0;
if (elf->class == ELFCLASS32)
{
Elf32_Shdr *shdr = strscn->shdr.e32 ?: __elf32_getshdr_rdlock (strscn);
@@ -96,6 +97,7 @@ elf_strptr (elf, idx, offset)
goto out;
}
+ sh_size = shdr->sh_size;
if (unlikely (offset >= shdr->sh_size))
{
/* The given offset is too big, it is beyond this section. */
@@ -113,6 +115,7 @@ elf_strptr (elf, idx, offset)
goto out;
}
+ sh_size = shdr->sh_size;
if (unlikely (offset >= shdr->sh_size))
{
/* The given offset is too big, it is beyond this section. */
@@ -141,7 +144,14 @@ elf_strptr (elf, idx, offset)
// rawdata_base can be set while rawdata.d hasn't been
// initialized yet (when data_read is zero). So we cannot just
// look at the rawdata.d.d_size.
- result = &strscn->rawdata_base[offset];
+
+ /* Make sure the string is NUL terminated. Start from the end,
+ which very likely is a NUL char. */
+ if (likely (memrchr (&strscn->rawdata_base[offset],
+ '\0', sh_size - offset) != NULL))
+ result = &strscn->rawdata_base[offset];
+ else
+ __libelf_seterrno (ELF_E_INVALID_INDEX);
}
else
{
@@ -153,7 +163,16 @@ elf_strptr (elf, idx, offset)
if (offset >= (size_t) dl->data.d.d_off
&& offset < dl->data.d.d_off + dl->data.d.d_size)
{
- result = (char *) dl->data.d.d_buf + (offset - dl->data.d.d_off);
+ /* Make sure the string is NUL terminated. Start from
+ the end, which very likely is a NUL char. */
+ if (likely (memrchr ((char *) dl->data.d.d_buf
+ + (offset - dl->data.d.d_off), '\0',
+ (dl->data.d.d_size
+ - (offset - dl->data.d.d_off))) != NULL))
+ result = ((char *) dl->data.d.d_buf
+ + (offset - dl->data.d.d_off));
+ else
+ __libelf_seterrno (ELF_E_INVALID_INDEX);
break;
}
--
1.8.3.1
8 years, 9 months
[PATCH] libelf: elf_strptr should use datalist when data has been added to section.
by Mark Wielaard
This oneliner patch relies on the "libelf: Fix elf_newdata when raw ELF
file/image data is available." fix.
elf_strptr always used the rawdata when available. But when data has been
added to the section it should find the correct buffer in the datalist.
Adds a large testcase that checks various ways of adding and extracting
strings from a section.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libelf/ChangeLog | 5 +
libelf/elf_strptr.c | 18 ++-
tests/ChangeLog | 7 +
tests/Makefile.am | 5 +-
tests/elfstrtab.c | 396 ++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 423 insertions(+), 8 deletions(-)
create mode 100644 tests/elfstrtab.c
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index c43a7fe..8bf1256 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,8 @@
+2015-01-21 Mark Wielaard <mjw(a)redhat.com>
+
+ * elf_strptr.c (elf_strptr): Check data_list_rear == NULL instead
+ of rawdata_base != NULL before using rawdata directly.
+
2015-01-20 Mark Wielaard <mjw(a)redhat.com>
* libelfP.h (__elf_strptr_internal): New function declaration.
diff --git a/libelf/elf_strptr.c b/libelf/elf_strptr.c
index f30a06f..62936a0 100644
--- a/libelf/elf_strptr.c
+++ b/libelf/elf_strptr.c
@@ -131,12 +131,18 @@ elf_strptr (elf, idx, offset)
goto out;
}
- if (likely (strscn->rawdata_base != NULL))
- // XXX Is this correct if a file is read and then new data is added
- // XXX to the string section? Likely needs to check offset against
- // XXX size of rawdata_base buffer and then iterate over rest of the
- // XXX list.
- result = &strscn->rawdata_base[offset];
+ if (likely (strscn->data_list_rear == NULL))
+ {
+ // XXX The above is currently correct since elf_newdata will
+ // make sure to convert the rawdata into the datalist if
+ // necessary. But it would be more efficient to keep the rawdata
+ // unconverted and only then iterate over the rest of the (newly
+ // added data) list. Note that when the ELF file is mmapped
+ // rawdata_base can be set while rawdata.d hasn't been
+ // initialized yet (when data_read is zero). So we cannot just
+ // look at the rawdata.d.d_size.
+ result = &strscn->rawdata_base[offset];
+ }
else
{
/* This is a file which is currently created. Use the list of
diff --git a/tests/ChangeLog b/tests/ChangeLog
index d41d0e1..97c7ab8 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,10 @@
+2015-01-21 Mark Wielaard <mjw(a)redhat.com>
+
+ * Makefile.am (check_PROGRAMS): Add elfstrtab.
+ (TESTS): Likewise.
+ (elfstrtab_LDADD): New variable.
+ * elfstrtab.c: New test.
+
2015-01-20 Mark Wielaard <mjw(a)redhat.com>
* Makefile.am (check_PROGRAMS): Add newdata.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 4420e8b..5ba8cdd 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -51,7 +51,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
dwfl-report-elf-align varlocs backtrace backtrace-child \
backtrace-data backtrace-dwarf debuglink debugaltlink \
buildid deleted deleted-lib.so aggregate_size vdsosyms \
- getsrc_die strptr newdata
+ getsrc_die strptr newdata elfstrtab
asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
asm-tst6 asm-tst7 asm-tst8 asm-tst9
@@ -113,7 +113,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
run-backtrace-demangle.sh run-stack-d-test.sh run-stack-i-test.sh \
run-readelf-dwz-multi.sh run-allfcts-multi.sh run-deleted.sh \
run-linkmap-cut.sh run-aggregate-size.sh vdsosyms run-readelf-A.sh \
- run-getsrc-die.sh run-strptr.sh newdata
+ run-getsrc-die.sh run-strptr.sh newdata elfstrtab
if !BIARCH
export ELFUTILS_DISABLE_BIARCH = 1
@@ -427,6 +427,7 @@ vdsosyms_LDADD = $(libdw) $(libelf)
getsrc_die_LDADD = $(libdw) $(libelf)
strptr_LDADD = $(libelf)
newdata_LDADD = $(libelf)
+elfstrtab_LDADD = $(libelf)
if GCOV
check: check-am coverage
diff --git a/tests/elfstrtab.c b/tests/elfstrtab.c
new file mode 100644
index 0000000..c27d6cf
--- /dev/null
+++ b/tests/elfstrtab.c
@@ -0,0 +1,396 @@
+/* Test program for elf_strptr function.
+ Copyright (C) 2015 Red Hat, Inc.
+ This file is part of elfutils.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include ELFUTILS_HEADER(elf)
+#include <gelf.h>
+
+
+/* Index of last string added. Returned by add_string (). */
+static size_t stridx = 0;
+
+/* Some random strings. */
+static char *str1;
+static size_t str1_off;
+static char *str2;
+static size_t str2_off;
+static char *str3;
+static size_t str3_off;
+
+/* First three strings we write out. They should always be there. */
+static char *orig_str1;
+static size_t orig_str1_off;
+static char *orig_str2;
+static size_t orig_str2_off;
+static char *orig_str3;
+static size_t orig_str3_off;
+
+static void
+check_orig_strings (Elf *elf, int ndx, const char *msg)
+{
+ printf ("checking orig strings: %s\n", msg);
+
+ const char *str = elf_strptr (elf, ndx, 0);
+ printf ("\t'%s'\n", str);
+ if (str == NULL || strcmp ("", str) != 0)
+ exit (1);
+
+ str = elf_strptr (elf, ndx, 1);
+ printf ("\t'%s'\n", str);
+ if (str == NULL || strcmp (".strings", str) != 0)
+ exit (1);
+
+ str = elf_strptr (elf, ndx, orig_str1_off);
+ printf ("\t'%s'\n", str);
+ if (str == NULL || strcmp (orig_str1, str) != 0)
+ exit (1);
+
+ str = elf_strptr (elf, ndx, orig_str2_off);
+ printf ("\t'%s'\n", str);
+ if (str == NULL || strcmp (orig_str2, str) != 0)
+ exit (1);
+
+ str = elf_strptr (elf, ndx, orig_str3_off);
+ printf ("\t'%s'\n", str);
+ if (str == NULL || strcmp (orig_str3, str) != 0)
+ exit (1);
+}
+
+static void
+check_strings (Elf *elf, int ndx, const char *msg)
+{
+ check_orig_strings (elf, ndx, msg);
+
+ const char *str = elf_strptr (elf, ndx, str1_off);
+ printf ("\t'%s'\n", str);
+ if (str == NULL || strcmp (str1, str) != 0)
+ exit (1);
+
+ str = elf_strptr (elf, ndx, str2_off);
+ printf ("\t'%s'\n", str);
+ if (str == NULL || strcmp (str2, str) != 0)
+ exit (1);
+
+ str = elf_strptr (elf, ndx, str3_off);
+ printf ("\t'%s'\n", str);
+ if (str == NULL || strcmp (str3, str) != 0)
+ exit (1);
+}
+
+/* Adds a string and returns the offset in the section. */
+static size_t
+add_string (Elf_Scn *scn, char *str)
+{
+ size_t lastidx = stridx;
+ size_t size = strlen (str) + 1;
+
+ Elf_Data *data = elf_newdata (scn);
+ if (data == NULL)
+ {
+ printf ("cannot create data SHSTRTAB section: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ data->d_buf = str;
+ data->d_type = ELF_T_BYTE;
+ data->d_size = size;
+ data->d_align = 1;
+ data->d_version = EV_CURRENT;
+
+ stridx += size;
+ printf ("add_string: '%s', stridx: %zd, lastidx: %zd\n",
+ str, stridx, lastidx);
+ return lastidx;
+}
+
+static void
+check_elf (const char *fname, int class, int use_mmap)
+{
+ printf ("\nfname: %s\n", fname);
+ stridx = 0;
+
+ int fd = open (fname, O_RDWR | O_CREAT | O_TRUNC, 0666);
+ if (fd == -1)
+ {
+ printf ("cannot open `%s': %s\n", fname, strerror (errno));
+ exit (1);
+ }
+
+ Elf *elf = elf_begin (fd, use_mmap ? ELF_C_WRITE_MMAP : ELF_C_WRITE, NULL);
+ if (elf == NULL)
+ {
+ printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ // Create an ELF header.
+ if (gelf_newehdr (elf, class) == 0)
+ {
+ printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ GElf_Ehdr ehdr_mem;
+ GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+ if (ehdr == NULL)
+ {
+ printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ // Initialize header.
+ ehdr->e_ident[EI_DATA] = class == ELFCLASS64 ? ELFDATA2LSB : ELFDATA2MSB;
+ ehdr->e_ident[EI_OSABI] = ELFOSABI_GNU;
+ ehdr->e_type = ET_NONE;
+ ehdr->e_machine = EM_X86_64;
+ ehdr->e_version = EV_CURRENT;
+
+ // Create strings section.
+ Elf_Scn *scn = elf_newscn (elf);
+ if (scn == NULL)
+ {
+ printf ("cannot create strings section: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ // Add an empty string to the table as NUL entry for section zero.
+ add_string (scn, "");
+
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+ if (shdr == NULL)
+ {
+ printf ("cannot get header for strings section: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ shdr->sh_type = SHT_STRTAB;
+ shdr->sh_flags = 0;
+ shdr->sh_addr = 0;
+ shdr->sh_link = SHN_UNDEF;
+ shdr->sh_info = SHN_UNDEF;
+ shdr->sh_addralign = 1;
+ shdr->sh_entsize = 0;
+ shdr->sh_name = add_string (scn, ".strings");
+
+ // We have to store the section strtab index in the ELF header.
+ // So sections have actual names.
+ int ndx = elf_ndxscn (scn);
+ ehdr->e_shstrndx = ndx;
+
+ if (gelf_update_ehdr (elf, ehdr) == 0)
+ {
+ printf ("cannot update ELF header: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ // Add some random strings. These are the original ones. They should
+ // always be there (together with the empty "" and .strings section
+ // name strings.
+ orig_str1 = "elfutils";
+ orig_str1_off = add_string (scn, orig_str1);
+ orig_str2 = "strtabelf";
+ orig_str2_off = add_string (scn, orig_str2);
+ orig_str3 = "three";
+ orig_str3_off = add_string (scn, orig_str3);
+
+ // Finished strings section, update the header.
+ if (gelf_update_shdr (scn, shdr) == 0)
+ {
+ printf ("cannot update STRTAB section header: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ // Let the library compute the internal structure information.
+ if (elf_update (elf, ELF_C_NULL) < 0)
+ {
+ printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ // Check our strings are there.
+ check_orig_strings (elf, ndx, "first elf_update, before write");
+
+ // Write everything to disk.
+ if (elf_update (elf, ELF_C_WRITE) < 0)
+ {
+ printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ // Check out strings are there.
+ check_orig_strings (elf, ndx, "first elf_update, after write");
+
+ // Add some more random strings. These will not be written to disk.
+ scn = elf_getscn (elf, ndx);
+ if (scn == NULL)
+ {
+ printf ("couldn't re-get strings section: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ str1 = "elfutils2";
+ str1_off = add_string (scn, str1);
+ str2 = "strtabelf2";
+ str2_off = add_string (scn, str2);
+ str3 = "three2";
+ str3_off = add_string (scn, str3);
+
+ // Update internal structure information again.
+ if (elf_update (elf, ELF_C_NULL) < 0)
+ {
+ printf ("failure in re-elf_update(NULL): %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ // Check our new strings are there.
+ check_strings (elf, ndx, "first extra strings");
+
+ if (elf_end (elf) != 0)
+ {
+ printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ close (fd);
+
+ /* Read the ELF from disk now. */
+ fd = open (fname, O_RDWR, 0666);
+ if (fd == -1)
+ {
+ printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
+ exit (1);
+ }
+
+ elf = elf_begin (fd, use_mmap ? ELF_C_RDWR_MMAP : ELF_C_RDWR, NULL);
+ if (elf == NULL)
+ {
+ printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ /* Are our strings there? */
+ check_orig_strings (elf, ndx, "read ELF file, orig strings");
+
+ // Add some more random strings.
+ scn = elf_getscn (elf, ndx);
+ if (scn == NULL)
+ {
+ printf ("couldn't re-get strings section: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ shdr = gelf_getshdr (scn, &shdr_mem);
+ if (shdr == NULL)
+ {
+ printf ("cannot get header for strings section: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ // Reset stridx to end of section.
+ printf ("sh_size: %" PRIu64 "\n", shdr->sh_size);
+ stridx = shdr->sh_size;
+
+ str1 = "0123456789";
+ str1_off = add_string (scn, str1);
+ str2 = "supercalifragilisticexpialidocious";
+ str2_off = add_string (scn, str2);
+ str3 = "forty-two";
+ str3_off = add_string (scn, str3);
+
+ // Update internal structure information.
+ if (elf_update (elf, ELF_C_NULL) < 0)
+ {
+ printf ("failure in rw-elf_update(NULL): %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ /* Check our new strings are there. */
+ check_strings (elf, ndx, "read file, added strings");
+
+ // Write updated ELF file.
+ if (elf_update (elf, ELF_C_WRITE) < 0)
+ {
+ printf ("failure in re-elf_update(NULL): %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ if (elf_end (elf) != 0)
+ {
+ printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ close (fd);
+
+ // And read it in one last time.
+ fd = open (fname, O_RDONLY, 0666);
+ if (fd == -1)
+ {
+ printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
+ exit (1);
+ }
+
+ elf = elf_begin (fd, use_mmap ? ELF_C_READ_MMAP : ELF_C_READ, NULL);
+ if (elf == NULL)
+ {
+ printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ /* Are all our strings there? */
+ check_strings (elf, ndx, "all together now");
+
+ if (elf_end (elf) != 0)
+ {
+ printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ close (fd);
+
+ unlink (fname);
+}
+
+int
+main (int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused)))
+{
+ elf_version (EV_CURRENT);
+
+ // Fill holes with something non-zero to more easily spot
+ // unterminated strings.
+ elf_fill ('X');
+
+ check_elf ("strtab.elf.32", ELFCLASS32, 0);
+ check_elf ("strtab.elf.32.mmap", ELFCLASS32, 1);
+ check_elf ("strtab.elf.64", ELFCLASS64, 0);
+ check_elf ("strtab.elf.64.mmap", ELFCLASS64, 1);
+
+ return 0;
+}
+
--
1.8.3.1
8 years, 9 months
[PATCH] libelf: Fix elf_newdata when raw data has been read, but not converted.
by Mark Wielaard
When ELF data for a section has been read by elf_rawdata, data_read
and rawdata_base are set, but data_list_rear will not be set until the
data will be converted (by elf_getdata). elf_newdata would overwrite
the existing data in that case.
Add newdata test that calls elf_newdata before and after elf_rawdata
and elf_getdata and checks the new size of the section.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libelf/ChangeLog | 4 +
libelf/elf_newdata.c | 13 +-
tests/ChangeLog | 7 +
tests/Makefile.am | 5 +-
tests/newdata.c | 365 +++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 390 insertions(+), 4 deletions(-)
create mode 100644 tests/newdata.c
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 6699052..36a6031 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,5 +1,9 @@
2015-01-20 Mark Wielaard <mjw(a)redhat.com>
+ * elf_newdata.c (elf_newdata): Check scn->rawdata_base.
+
+2015-01-20 Mark Wielaard <mjw(a)redhat.com>
+
* elf_strptr.c (elf_strptr): Call __elf[32|64]_getshdr_rdlock if
necessary.
diff --git a/libelf/elf_newdata.c b/libelf/elf_newdata.c
index 90d1813..06baeb5 100644
--- a/libelf/elf_newdata.c
+++ b/libelf/elf_newdata.c
@@ -1,5 +1,5 @@
/* Create new, empty section data.
- Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2015 Red Hat, Inc.
This file is part of elfutils.
Contributed by Ulrich Drepper <drepper(a)redhat.com>, 1998.
@@ -64,7 +64,16 @@ elf_newdata (Elf_Scn *scn)
rwlock_wrlock (scn->elf->lock);
- if (scn->data_read && scn->data_list_rear == NULL)
+ /* data_read is set when data has been read from the ELF image or
+ when a new section has been created by elf_newscn. If data has
+ been read from the ELF image, then rawdata_base will point to raw
+ data. If data_read has been set by elf_newscn, then rawdata_base
+ will be NULL. data_list_rear will be set by elf_getdata if the
+ data has been converted, or by this function, elf_newdata, when
+ new data has been added. */
+ if (scn->data_read
+ && scn->rawdata_base == NULL
+ && scn->data_list_rear == NULL)
{
/* This means the section was created by the user and this is the
first data. */
diff --git a/tests/ChangeLog b/tests/ChangeLog
index f94d9be..d41d0e1 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,5 +1,12 @@
2015-01-20 Mark Wielaard <mjw(a)redhat.com>
+ * Makefile.am (check_PROGRAMS): Add newdata.
+ (TESTS): Likewise.
+ (newdata_LDADD): new variable.
+ * newdata.c: New test.
+
+2015-01-20 Mark Wielaard <mjw(a)redhat.com>
+
* strptr.c: New file.
* run-strptr.sh: New test.
* Makefile.am (check_PROGRAMS): Add strptr.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index c3364a2..4420e8b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -51,7 +51,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
dwfl-report-elf-align varlocs backtrace backtrace-child \
backtrace-data backtrace-dwarf debuglink debugaltlink \
buildid deleted deleted-lib.so aggregate_size vdsosyms \
- getsrc_die strptr
+ getsrc_die strptr newdata
asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
asm-tst6 asm-tst7 asm-tst8 asm-tst9
@@ -113,7 +113,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
run-backtrace-demangle.sh run-stack-d-test.sh run-stack-i-test.sh \
run-readelf-dwz-multi.sh run-allfcts-multi.sh run-deleted.sh \
run-linkmap-cut.sh run-aggregate-size.sh vdsosyms run-readelf-A.sh \
- run-getsrc-die.sh run-strptr.sh
+ run-getsrc-die.sh run-strptr.sh newdata
if !BIARCH
export ELFUTILS_DISABLE_BIARCH = 1
@@ -426,6 +426,7 @@ aggregate_size_LDADD = $(libdw) $(libelf)
vdsosyms_LDADD = $(libdw) $(libelf)
getsrc_die_LDADD = $(libdw) $(libelf)
strptr_LDADD = $(libelf)
+newdata_LDADD = $(libelf)
if GCOV
check: check-am coverage
diff --git a/tests/newdata.c b/tests/newdata.c
new file mode 100644
index 0000000..7dfe962
--- /dev/null
+++ b/tests/newdata.c
@@ -0,0 +1,365 @@
+/* Test program for elf_newdata function.
+ Copyright (C) 2015 Red Hat, Inc.
+ This file is part of elfutils.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include ELFUTILS_HEADER(elf)
+#include <gelf.h>
+
+// Random data string (16 bytes).
+static char *DATA = "123456789ABCDEF";
+static size_t DATA_LEN = 16;
+
+static void
+add_section_data (Elf *elf, char *buf, size_t len)
+{
+ printf ("Adding %zd bytes.\n", len);
+
+ Elf_Scn *scn = elf_getscn (elf, 1);
+ if (scn == NULL)
+ {
+ printf ("couldn't get data section: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ Elf_Data *data = elf_newdata (scn);
+ if (data == NULL)
+ {
+ printf ("cannot create newdata for section: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ data->d_buf = buf;
+ data->d_type = ELF_T_BYTE;
+ data->d_size = len;
+ data->d_align = 1;
+ data->d_version = EV_CURRENT;
+
+ // Let the library compute the internal structure information.
+ if (elf_update (elf, ELF_C_NULL) < 0)
+ {
+ printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+}
+
+static Elf *
+create_elf (int fd, int class)
+{
+ Elf *elf = elf_begin (fd, ELF_C_WRITE, NULL);
+ if (elf == NULL)
+ {
+ printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ // Create an ELF header.
+ if (gelf_newehdr (elf, class) == 0)
+ {
+ printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ GElf_Ehdr ehdr_mem;
+ GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+ if (ehdr == NULL)
+ {
+ printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ // Initialize header.
+ ehdr->e_ident[EI_DATA] = ELFCLASS32 ? ELFDATA2LSB : ELFDATA2MSB;
+ ehdr->e_ident[EI_OSABI] = ELFOSABI_GNU;
+ ehdr->e_type = ET_NONE;
+ ehdr->e_machine = class == ELFCLASS32 ? EM_PPC : EM_X86_64;
+ ehdr->e_version = EV_CURRENT;
+
+ // Update the ELF header.
+ if (gelf_update_ehdr (elf, ehdr) == 0)
+ {
+ printf ("cannot update ELF header: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ // Create a section.
+ Elf_Scn *scn = elf_newscn (elf);
+ if (scn == NULL)
+ {
+ printf ("cannot create new section: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+ if (shdr == NULL)
+ {
+ printf ("cannot get header for data section: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ shdr->sh_type = SHT_PROGBITS;
+ shdr->sh_flags = 0;
+ shdr->sh_addr = 0;
+ shdr->sh_link = SHN_UNDEF;
+ shdr->sh_info = SHN_UNDEF;
+ shdr->sh_addralign = 1;
+ shdr->sh_entsize = 1;
+ shdr->sh_name = 0;
+
+ // Finish section, update the header.
+ if (gelf_update_shdr (scn, shdr) == 0)
+ {
+ printf ("cannot update header for DATA section: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ // Add some data to the section.
+ add_section_data (elf, DATA, DATA_LEN);
+
+ // Write everything to disk.
+ if (elf_update (elf, ELF_C_WRITE) < 0)
+ {
+ printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ return elf;
+}
+
+static Elf *
+read_elf (int fd)
+{
+ printf ("Reading ELF file\n");
+ Elf *elf = elf_begin (fd, ELF_C_RDWR, NULL);
+ if (elf == NULL)
+ {
+ printf ("cannot create ELF descriptor read-again: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ return elf;
+}
+
+static void
+check_section_size (Elf *elf, size_t size)
+{
+ Elf_Scn *scn = elf_getscn (elf, 1);
+ if (scn == NULL)
+ {
+ printf ("couldn't get data section: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+ if (shdr == NULL)
+ {
+ printf ("cannot get header for DATA section: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ if (shdr->sh_size == size)
+ printf ("OK %zd bytes.\n", size);
+ else
+ {
+ printf ("BAD size, expected %zd, got %" PRIu64 "\n",
+ size, shdr->sh_size);
+ exit (-1);
+ }
+}
+
+static void
+check_elf (int class)
+{
+ static const char *fname;
+ fname = class == ELFCLASS32 ? "newdata.elf32" : "newdata.elf64";
+
+ printf ("check_elf: %s\n", fname);
+
+ int fd = open (fname, O_RDWR|O_CREAT|O_TRUNC, 00666);
+ if (fd == -1)
+ {
+ printf ("cannot create `%s': %s\n", fname, strerror (errno));
+ exit (1);
+ }
+
+ Elf *elf = create_elf (fd, class);
+ check_section_size (elf, DATA_LEN);
+
+ // Add some more data (won't be written to disk).
+ add_section_data (elf, DATA, DATA_LEN);
+ check_section_size (elf, 2 * DATA_LEN);
+
+ if (elf_end (elf) != 0)
+ {
+ printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ close (fd);
+
+ // Read the ELF from disk now. And add new data directly.
+ fd = open (fname, O_RDONLY);
+ if (fd == -1)
+ {
+ printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
+ exit (1);
+ }
+
+ elf = read_elf (fd);
+ check_section_size (elf, DATA_LEN);
+
+ // Add some more data.
+ add_section_data (elf, DATA, DATA_LEN);
+ check_section_size (elf, 2 * DATA_LEN);
+
+ // And some more.
+ add_section_data (elf, DATA, DATA_LEN);
+ check_section_size (elf, 3 * DATA_LEN);
+
+ if (elf_end (elf) != 0)
+ {
+ printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ close (fd);
+
+ // Read the ELF from disk now. And add new data after raw reading.
+ fd = open (fname, O_RDONLY);
+ if (fd == -1)
+ {
+ printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
+ exit (1);
+ }
+
+ elf = read_elf (fd);
+ check_section_size (elf, DATA_LEN);
+
+ // Get raw data before adding new data.
+ Elf_Scn *scn = elf_getscn (elf, 1);
+ if (scn == NULL)
+ {
+ printf ("couldn't get data section: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ printf ("elf_rawdata\n");
+ Elf_Data *data = elf_rawdata (scn, NULL);
+ if (data == NULL)
+ {
+ printf ("couldn't get raw data from section: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ if (data->d_size != DATA_LEN)
+ {
+ printf ("Unexpected Elf_Data: %zd", data->d_size);
+ exit (1);
+ }
+
+ // Now add more data.
+ add_section_data (elf, DATA, DATA_LEN);
+ check_section_size (elf, 2 * DATA_LEN);
+
+ // And some more.
+ add_section_data (elf, DATA, DATA_LEN);
+ check_section_size (elf, 3 * DATA_LEN);
+
+ if (elf_end (elf) != 0)
+ {
+ printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ close (fd);
+
+ // Read the ELF from disk now. And add new data after data reading.
+ fd = open (fname, O_RDONLY);
+ if (fd == -1)
+ {
+ printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
+ exit (1);
+ }
+
+ elf = read_elf (fd);
+ check_section_size (elf, DATA_LEN);
+
+ // Get raw data before adding new data.
+ scn = elf_getscn (elf, 1);
+ if (scn == NULL)
+ {
+ printf ("couldn't get data section: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ printf ("elf_getdata\n");
+ data = elf_getdata (scn, NULL);
+ if (data == NULL)
+ {
+ printf ("couldn't get raw data from section: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ if (data->d_size != DATA_LEN)
+ {
+ printf ("Unexpected Elf_Data: %zd", data->d_size);
+ exit (1);
+ }
+
+ // Now add more data.
+ add_section_data (elf, DATA, DATA_LEN);
+ check_section_size (elf, 2 * DATA_LEN);
+
+ // And some more.
+ add_section_data (elf, DATA, DATA_LEN);
+ check_section_size (elf, 3 * DATA_LEN);
+
+ if (elf_end (elf) != 0)
+ {
+ printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ close (fd);
+
+ unlink (fname);
+}
+
+int
+main (int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused)))
+{
+ // Initialize libelf.
+ elf_version (EV_CURRENT);
+
+ check_elf (ELFCLASS32);
+ check_elf (ELFCLASS64);
+
+ return 0;
+}
--
1.8.3.1
8 years, 9 months
[PATCH] libelf: elf_strptr should fetch the shdr for the section if not yet known.
by Mark Wielaard
elf_strptr might be called before the shdrs are read in. In that case it
needs to explicitly call __elf[32|64]_getshdr_rdlock to check the section
type and size. The new strptr testcase triggers this corner case and crashes
before the fix.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libelf/ChangeLog | 5 +++
libelf/elf_strptr.c | 12 ++++---
tests/ChangeLog | 9 +++++
tests/Makefile.am | 7 ++--
tests/run-strptr.sh | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++
tests/strptr.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 218 insertions(+), 8 deletions(-)
create mode 100755 tests/run-strptr.sh
create mode 100644 tests/strptr.c
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index adfccf1..6699052 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,8 @@
+2015-01-20 Mark Wielaard <mjw(a)redhat.com>
+
+ * elf_strptr.c (elf_strptr): Call __elf[32|64]_getshdr_rdlock if
+ necessary.
+
2015-01-03 Mark Wielaard <mjw(a)redhat.com>
* version_xlate.h (elf_cvt_Verdef): Use memmove to copy src to dest.
diff --git a/libelf/elf_strptr.c b/libelf/elf_strptr.c
index 1f40429..f30a06f 100644
--- a/libelf/elf_strptr.c
+++ b/libelf/elf_strptr.c
@@ -1,5 +1,5 @@
/* Return string pointer from string section.
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2008, 2009 Red Hat, Inc.
+ Copyright (C) 1998-2002, 2004, 2008, 2009, 2015 Red Hat, Inc.
This file is part of elfutils.
Contributed by Ulrich Drepper <drepper(a)redhat.com>, 1998.
@@ -88,14 +88,15 @@ elf_strptr (elf, idx, offset)
if (elf->class == ELFCLASS32)
{
- if (unlikely (strscn->shdr.e32->sh_type != SHT_STRTAB))
+ Elf32_Shdr *shdr = strscn->shdr.e32 ?: __elf32_getshdr_rdlock (strscn);
+ if (unlikely (shdr->sh_type != SHT_STRTAB))
{
/* This is no string section. */
__libelf_seterrno (ELF_E_INVALID_SECTION);
goto out;
}
- if (unlikely (offset >= strscn->shdr.e32->sh_size))
+ if (unlikely (offset >= shdr->sh_size))
{
/* The given offset is too big, it is beyond this section. */
__libelf_seterrno (ELF_E_OFFSET_RANGE);
@@ -104,14 +105,15 @@ elf_strptr (elf, idx, offset)
}
else
{
- if (unlikely (strscn->shdr.e64->sh_type != SHT_STRTAB))
+ Elf64_Shdr *shdr = strscn->shdr.e64 ?: __elf64_getshdr_rdlock (strscn);
+ if (unlikely (shdr->sh_type != SHT_STRTAB))
{
/* This is no string section. */
__libelf_seterrno (ELF_E_INVALID_SECTION);
goto out;
}
- if (unlikely (offset >= strscn->shdr.e64->sh_size))
+ if (unlikely (offset >= shdr->sh_size))
{
/* The given offset is too big, it is beyond this section. */
__libelf_seterrno (ELF_E_OFFSET_RANGE);
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 87a7ce7..f94d9be 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,12 @@
+2015-01-20 Mark Wielaard <mjw(a)redhat.com>
+
+ * strptr.c: New file.
+ * run-strptr.sh: New test.
+ * Makefile.am (check_PROGRAMS): Add strptr.
+ (TESTS): Add run-strptr.sh.
+ (EXTRA_DIST): Likewise.
+ (strptr_LDADD): New variable.
+
2015-01-15 Mark Wielaard <mjw(a)redhat.com>
* deleted.c (main): Call prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY).
diff --git a/tests/Makefile.am b/tests/Makefile.am
index cbc1eb2..c3364a2 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -51,7 +51,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
dwfl-report-elf-align varlocs backtrace backtrace-child \
backtrace-data backtrace-dwarf debuglink debugaltlink \
buildid deleted deleted-lib.so aggregate_size vdsosyms \
- getsrc_die
+ getsrc_die strptr
asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
asm-tst6 asm-tst7 asm-tst8 asm-tst9
@@ -113,7 +113,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
run-backtrace-demangle.sh run-stack-d-test.sh run-stack-i-test.sh \
run-readelf-dwz-multi.sh run-allfcts-multi.sh run-deleted.sh \
run-linkmap-cut.sh run-aggregate-size.sh vdsosyms run-readelf-A.sh \
- run-getsrc-die.sh
+ run-getsrc-die.sh run-strptr.sh
if !BIARCH
export ELFUTILS_DISABLE_BIARCH = 1
@@ -284,7 +284,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
testfile-sizes3.o.bz2 \
run-readelf-A.sh testfileppc32attrs.o.bz2 \
testfile-debug-types.bz2 \
- run-getsrc-die.sh
+ run-getsrc-die.sh run-strptr.sh
if USE_VALGRIND
valgrind_cmd='valgrind -q --error-exitcode=1 --run-libc-freeres=no'
@@ -425,6 +425,7 @@ deleted_lib_so_CFLAGS = -fPIC -fasynchronous-unwind-tables
aggregate_size_LDADD = $(libdw) $(libelf)
vdsosyms_LDADD = $(libdw) $(libelf)
getsrc_die_LDADD = $(libdw) $(libelf)
+strptr_LDADD = $(libelf)
if GCOV
check: check-am coverage
diff --git a/tests/run-strptr.sh b/tests/run-strptr.sh
new file mode 100755
index 0000000..af90a02
--- /dev/null
+++ b/tests/run-strptr.sh
@@ -0,0 +1,98 @@
+#! /bin/sh
+# Copyright (C) 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# A random 32bit and 64bit testfile
+testfiles testfile testfile10
+
+testrun_compare ${abs_top_builddir}/tests/strptr testfile <<\EOF
+Strings in section 32:
+[0] ''
+[1] '.symtab'
+[9] '.strtab'
+[11] '.shstrtab'
+[1b] '.interp'
+[23] '.note.ABI-tag'
+[31] '.hash'
+[37] '.dynsym'
+[3f] '.dynstr'
+[47] '.gnu.version'
+[54] '.gnu.version_r'
+[63] '.rel.got'
+[6c] '.rel.plt'
+[75] '.init'
+[7b] '.plt'
+[80] '.text'
+[86] '.fini'
+[8c] '.rodata'
+[94] '.data'
+[9a] '.eh_frame'
+[a4] '.ctors'
+[ab] '.dtors'
+[b2] '.got'
+[b7] '.dynamic'
+[c0] '.sbss'
+[c6] '.bss'
+[cb] '.stab'
+[d1] '.stabstr'
+[da] '.comment'
+[e3] '.debug_aranges'
+[f2] '.debug_pubnames'
+[102] '.debug_info'
+[10e] '.debug_abbrev'
+[11c] '.debug_line'
+[128] '.note'
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/strptr testfile10 <<\EOF
+Strings in section 30:
+[0] ''
+[1] '.symtab'
+[9] '.strtab'
+[11] '.shstrtab'
+[1b] '.hash'
+[21] '.dynsym'
+[29] '.dynstr'
+[31] '.gnu.version'
+[3e] '.gnu.version_r'
+[4d] '.rela.dyn'
+[57] '.init'
+[5d] '.text'
+[63] '.fini'
+[69] '.eh_frame'
+[73] '.data'
+[79] '.dynamic'
+[82] '.ctors'
+[89] '.dtors'
+[90] '.jcr'
+[95] '.plt'
+[9a] '.got'
+[9f] '.sdata'
+[a6] '.sbss'
+[ac] '.bss'
+[b1] '.comment'
+[ba] '.debug_aranges'
+[c9] '.debug_pubnames'
+[d9] '.debug_abbrev'
+[e7] '.debug_line'
+[f3] '.debug_frame'
+[100] '.debug_str'
+[10b] '.rela.debug_info'
+EOF
+
+exit 0
diff --git a/tests/strptr.c b/tests/strptr.c
new file mode 100644
index 0000000..759664a
--- /dev/null
+++ b/tests/strptr.c
@@ -0,0 +1,95 @@
+/* Test program for elf_strptr function.
+ Copyright (C) 2015 Red Hat, Inc.
+ This file is part of elfutils.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include ELFUTILS_HEADER(elf)
+#include <gelf.h>
+
+int
+main (int argc, char *argv[])
+{
+ if (argc != 2)
+ {
+ printf ("No ELF file given as argument");
+ exit (1);
+ }
+
+ const char *fname = argv[1];
+
+ // Initialize libelf.
+ elf_version (EV_CURRENT);
+
+ /* Read the ELF from disk now. */
+ int fd = open (fname, O_RDONLY);
+ if (fd == -1)
+ {
+ printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
+ exit (1);
+ }
+
+ Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
+ if (elf == NULL)
+ {
+ printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ size_t ndx;
+ if (elf_getshdrstrndx (elf, &ndx) != 0)
+ {
+ printf ("cannot get section header table index: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ if (ndx == SHN_UNDEF)
+ {
+ printf ("ELF file `%s' doesn't have a section header table index", fname);
+ exit (1);
+ }
+
+ printf ("Strings in section %zd:\n", ndx);
+
+ size_t off = 0;
+ const char *str = elf_strptr (elf, ndx, off);
+ while (str != NULL)
+ {
+ printf ("[%zx] '%s'\n", off, str);
+ off += strlen (str) + 1;
+ str = elf_strptr (elf, ndx, off);
+ }
+
+ if (elf_end (elf) != 0)
+ {
+ printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+ exit (1);
+ }
+
+ close (fd);
+
+ return 0;
+}
--
1.8.3.1
8 years, 9 months
[COMMITTED] libebl.h: Add comment from README that this is completely UNSUPPORTED.
by Mark Wielaard
Since there was another accident where a project was using libebl functions
directly I added the following warning to the libebl.h header file.
Make it really, really clear that the libebl interface is NOT source and
NOT abi compatible and we will break any users.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libebl/ChangeLog | 5 +++++
libebl/libebl.h | 15 ++++++++++++++-
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/libebl/ChangeLog b/libebl/ChangeLog
index 5e635f2..3655e72 100644
--- a/libebl/ChangeLog
+++ b/libebl/ChangeLog
@@ -1,3 +1,8 @@
+2015-01-27 Mark Wielaard <mjw(a)redhat.com>
+
+ * libebl.h: Add comment from README that this is completely
+ UNSUPPORTED.
+
2014-11-22 Mark Wielaard <mjw(a)redhat.com>
* ebl-hooks.h (bss_plt_p): Remove ehdr argument.
diff --git a/libebl/libebl.h b/libebl/libebl.h
index 7c3c764..7ead62c 100644
--- a/libebl/libebl.h
+++ b/libebl/libebl.h
@@ -1,5 +1,5 @@
/* Interface for libebl.
- Copyright (C) 2000-2010, 2013, 2014 Red Hat, Inc.
+ Copyright (C) 2000-2010, 2013, 2014, 2015 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -26,6 +26,19 @@
the GNU Lesser General Public License along with this program. If
not, see <http://www.gnu.org/licenses/>. */
+
+/* This is the interface for the Elfutils Backend Library.
+ It is a completely UNSUPPORTED interface. Don't use any libebl
+ function directly. These are only for internal elfutils backends
+ and tools. There is NO source or binary compatible guarantee.
+
+ The ABI of the backend modules is not guaranteed. Really, not guarantee
+ whatsoever. We are enforcing this in the code. The modules and their
+ users must match. No third-party EBL module are supported or allowed.
+ The only reason there are separate modules is to not have the code for
+ all architectures in all the binaries. */
+
+
#ifndef _LIBEBL_H
#define _LIBEBL_H 1
--
1.8.3.1
8 years, 10 months
malformed elf causes invalid shiftleft in readelf -S with ubsan
by Hanno Böck
Hi,
When compiling elfutils with undefined behaviour sanitizer
(-fsanitize=undefined) a warning will be shown indicating an invalid
shiftleft operation on the attached elf file:
readelf.c:1133:28: runtime error: left shift of 1 by 31 places cannot
be represented in type 'int'
Tested with elfutils-0.161. This was found with zzuf.
cu,
--
Hanno Böck
http://hboeck.de/
mail/jabber: hanno(a)hboeck.de
GPG: BBB51E42
8 years, 10 months
elfutils build error on fedora 19 ppc64
by Ashish Kumar9
I am trying to build elfutils package on Fedora 19 on ppc64 server .
During the build , I am observing few unit test failure issues as below
.However the community ppc build indicates successful build .
Is there any specific settings to be adopted to get the build successful ?
Build Error Log Extract Below :
============================================================================
Testsuite summary for elfutils 0.158
============================================================================
# TOTAL: 115
# PASS: 110
# SKIP: 1
# XFAIL: 0
# FAIL: 4
# XPASS: 0
# ERROR: 0
============================================================================
See tests/test-suite.log
Please report to https://bugzilla.redhat.com/
============================================================================
make[3]: *** [test-suite.log] Error 1
make[2]: *** [check-TESTS] Error 2
make[1]: *** [check-am] Error 2
make: *** [check-recursive] Error 1
+ cat tests/test-suite.log
==========================================
elfutils 0.158: tests/test-suite.log
==========================================
# TOTAL: 115
# PASS: 110
# SKIP: 1
# XFAIL: 0
# FAIL: 4
# XPASS: 0
# ERROR: 0
.. contents:: :depth: 2
FAIL: run-backtrace-native.sh
=============================
0x2b840000 0x2b870000
/centos/rpmbuild/BUILD/elfutils-0.158/tests/back trace-child
0x3fff80650000 0x3fff80840000 /usr/lib64/libc-2.17.so
0x3fff80850000 0x3fff80890000 /usr/lib64/libpthread-2.17.so
0x3fff808c0000 0x3fff808e0000 [vdso: 31447]
0x3fff808e0000 0x3fff80930000 /usr/lib64/ld-2.17.so
TID 31447:
# 0 0x3fff80867224 raise
# 1 0x2b84104c - 1 main
# 2 0x3fff806943ac - 1 generic_start_main.isra.0
TID 31450:
# 0 0x3fff80867224 raise
# 1 0x2b8413fc - 1 sigusr2
# 2 0x2b8414c8 - 1 stdarg
# 3 0x2b841534 - 1 backtracegen
# 4 0x2b841550 - 1 start
# 5 0x3fff8085c29c - 1 start_thread
# 6 0x3fff8077de10 - 1 __clone
/centos/rpmbuild/BUILD/elfutils-0.158/tests/backtrace:
dwfl_thread_getframes: No DWARF information found
/centos/rpmbuild/BUILD/elfutils-0.158/tests/backtrace:
dwfl_thread_getframes: No DWARF information found
# 1 0x2b84104c - 1 main
rmdir: failed to remove 'test-31431': Directory not empty
SKIP: run-backtrace-data.sh
===========================
/centos/rpmbuild/BUILD/elfutils-0.158/tests/backtrace-data: Unwinding not
suppor ted for this
architecture
data: arch not supported
FAIL: run-backtrace-native-biarch.sh
====================================
0x2f3d0000 0x2f400000
/centos/rpmbuild/BUILD/elfutils-0.158/tests/back trace-child-biarch
0x3fffab940000 0x3fffabb30000 /usr/lib64/libc-2.17.so
0x3fffabb40000 0x3fffabb80000 /usr/lib64/libpthread-2.17.so
0x3fffabbb0000 0x3fffabbd0000 [vdso: 31492]
0x3fffabbd0000 0x3fffabc20000 /usr/lib64/ld-2.17.so
TID 31492:
# 0 0x3fffabb57224 raise
# 1 0x2f3d104c - 1 main
# 2 0x3fffab9843ac - 1 generic_start_main.isra.0
TID 31493:
# 0 0x3fffabb57224 raise
# 1 0x2f3d13fc - 1 sigusr2
# 2 0x2f3d14c8 - 1 stdarg
# 3 0x2f3d1534 - 1 backtracegen
# 4 0x2f3d1550 - 1 start
# 5 0x3fffabb4c29c - 1 start_thread
# 6 0x3fffaba6de10 - 1 __clone
/centos/rpmbuild/BUILD/elfutils-0.158/tests/backtrace:
dwfl_thread_getframes: No DWARF information found
/centos/rpmbuild/BUILD/elfutils-0.158/tests/backtrace:
dwfl_thread_getframes: No DWARF information found
# 1 0x2f3d104c - 1 main
rmdir: failed to remove 'test-31472': Directory not empty
FAIL: run-backtrace-native-core.sh
==================================
backtrace: cannot read ELF core file: not a valid ELF file
backtrace-child-core.31513: no main
FAIL: run-backtrace-native-core-biarch.sh
=========================================
backtrace: cannot read ELF core file: not a valid ELF file
backtrace-child-biarch-core.31554: no main
**************************************************************************************************************************************
8 years, 10 months