[PATCH] Fix sanitize-undefined config check. Don't ALLOW_UNALIGNED when checking.
by Mark Wielaard
The -fsanitize=undefined check need to use AC_LINK_IFELSE to make sure
libubsan is installed. When doing undefined checking we should disable
ALLOW_UNALIGNED memory accesses to catch issues where we do unaligned
accesses by accident.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
ChangeLog | 5 +++++
configure.ac | 12 +++++++++---
lib/ChangeLog | 4 ++++
lib/eu-config.h | 3 ++-
4 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index f281f98..c67894e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2015-05-31 Mark Wielaard <mjw(a)redhat.com>
+
+ * configure.ac (use_undefined): Use AC_LINK_IFELSE. AC_DEFINE
+ CHECK_UNDEFINED.
+
2015-05-30 Mark Wielaard <mjw(a)redhat.com>
* configure.ac: Check for bunzip2. Check flex and bison are
diff --git a/configure.ac b/configure.ac
index 6386e96..58366d5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -202,13 +202,19 @@ if test "$use_undefined" = yes; then
old_CXXFLAGS="$CXXFLAGS"
# We explicitly use unaligned access when possible (see ALLOW_UNALIGNED)
# We want to fail immediately on first error, don't try to recover.
- CFLAGS="$CFLAGS -fsanitize=undefined -fno-sanitize=alignment -fno-sanitize-recover"
- CXXFLAGS="$CXXFLAGS -fsanitize=undefined -fno-sanitize=alignment -fno-sanitize-recover"
- AC_COMPILE_IFELSE([AC_LANG_SOURCE([])], use_undefined=yes, use_undefined=no)
+ CFLAGS="$CFLAGS -fsanitize=undefined -fno-sanitize-recover"
+ CXXFLAGS="$CXXFLAGS -fsanitize=undefined -fno-sanitize-recover"
+ AC_LINK_IFELSE([AC_LANG_SOURCE([int main (int argc, char **argv) { return 0; }])], use_undefined=yes, use_undefined=no)
AS_IF([test "x$use_undefined" != xyes],
AC_MSG_WARN([gcc undefined behaviour sanitizer not available])
CFLAGS="$old_CFLAGS" CXXFLAGS="$old_CXXFLAGS")
fi
+case $use_undefined in
+ yes) check_undefined_val=1 ;;
+ *) check_undefined_val=0 ;;
+esac
+AC_DEFINE_UNQUOTED(CHECK_UNDEFINED, $check_undefined_val,
+ [Building with -fsanitize=undefined or not])
AC_ARG_ENABLE([valgrind],
AS_HELP_STRING([--enable-valgrind],[run all tests under valgrind]),
diff --git a/lib/ChangeLog b/lib/ChangeLog
index 166f047..d04bf17 100644
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -1,3 +1,7 @@
+2015-05-31 Mark Wielaard <mjw(a)redhat.com>
+
+ * eu-config.h (ALLOW_UNALIGNED): Define when ! CHECK_UNDEFINED.
+
2015-04-23 Max Filippov <jcmvbkbc(a)gmail.com>
* eu-config.h: Use SYMBOL_VERSIONING as guard.
diff --git a/lib/eu-config.h b/lib/eu-config.h
index 5bb21c1..400cdc6 100644
--- a/lib/eu-config.h
+++ b/lib/eu-config.h
@@ -73,7 +73,8 @@
/* Define ALLOW_UNALIGNED if the architecture allows operations on
unaligned memory locations. */
-#if defined __i386__ || defined __x86_64__
+#define SANITIZE_UNDEFINED 1
+#if (defined __i386__ || defined __x86_64__) && ! CHECK_UNDEFINED
# define ALLOW_UNALIGNED 1
#else
# define ALLOW_UNALIGNED 0
--
2.4.2
8 years, 10 months
[PATCH] libdwfl: Don't assume auxv or r_debug data is properly aligned in link_map.
by Mark Wielaard
core file data isn't guaranteed to be alligned properly. Use
read_(4|8)ubyte_unaligned_noncvt to read values, types and addresses.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdwfl/ChangeLog | 7 +++++++
libdwfl/link_map.c | 25 +++++++++++++++----------
2 files changed, 22 insertions(+), 10 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index ffb34c0..f4e7484 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,5 +1,12 @@
2015-05-30 Mark Wielaard <mjw(a)redhat.com>
+ * link_map.c (check32): Use read_4ubyte_unaligned_noncvt to read
+ type and value.
+ (read_addrs): Use read_(4|8)ubyte_unaligned_noncvt or to read
+ adresses.
+
+2015-05-30 Mark Wielaard <mjw(a)redhat.com>
+
* find-debuginfo.c (dwfl_standard_find_debuginfo): Check file_name is
not NULL before calling canonicalize_file_name.
diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c
index a5a6968..030c600 100644
--- a/libdwfl/link_map.c
+++ b/libdwfl/link_map.c
@@ -58,8 +58,7 @@ auxv_format_probe (const void *auxv, size_t size,
inline bool check64 (size_t i)
{
/* The AUXV pointer might not even be naturally aligned for 64-bit
- data, because note payloads in a core file are not aligned.
- But we assume the data is 32-bit aligned. */
+ data, because note payloads in a core file are not aligned. */
uint64_t type = read_8ubyte_unaligned_noncvt (&u->a64[i].a_type);
uint64_t val = read_8ubyte_unaligned_noncvt (&u->a64[i].a_un.a_val);
@@ -83,15 +82,21 @@ auxv_format_probe (const void *auxv, size_t size,
inline bool check32 (size_t i)
{
- if (u->a32[i].a_type == BE32 (PROBE_TYPE)
- && u->a32[i].a_un.a_val == BE32 (PROBE_VAL32))
+ /* The AUXV pointer might not even be naturally aligned for 32-bit
+ data, because note payloads in a core file are not aligned. */
+
+ uint32_t type = read_4ubyte_unaligned_noncvt (&u->a32[i].a_type);
+ uint32_t val = read_4ubyte_unaligned_noncvt (&u->a32[i].a_un.a_val);
+
+ if (type == BE32 (PROBE_TYPE)
+ && val == BE32 (PROBE_VAL32))
{
*elfdata = ELFDATA2MSB;
return true;
}
- if (u->a32[i].a_type == LE32 (PROBE_TYPE)
- && u->a32[i].a_un.a_val == LE32 (PROBE_VAL32))
+ if (type == LE32 (PROBE_TYPE)
+ && val == LE32 (PROBE_VAL32))
{
*elfdata = ELFDATA2LSB;
return true;
@@ -285,19 +290,19 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
{
if (elfdata == ELFDATA2MSB)
for (size_t i = 0; i < n; ++i)
- addrs[i] = BE32 (in->a32[i]);
+ addrs[i] = BE32 (read_4ubyte_unaligned_noncvt (&in->a32[i]));
else
for (size_t i = 0; i < n; ++i)
- addrs[i] = LE32 (in->a32[i]);
+ addrs[i] = LE32 (read_4ubyte_unaligned_noncvt (&in->a32[i]));
}
else
{
if (elfdata == ELFDATA2MSB)
for (size_t i = 0; i < n; ++i)
- addrs[i] = BE64 (in->a64[i]);
+ addrs[i] = BE64 (read_8ubyte_unaligned_noncvt (&in->a64[i]));
else
for (size_t i = 0; i < n; ++i)
- addrs[i] = LE64 (in->a64[i]);
+ addrs[i] = LE64 (read_8ubyte_unaligned_noncvt (&in->a64[i]));
}
return false;
--
2.4.2
8 years, 10 months
Fix more unbounded stack usage when !ALLOW_UNALIGNED.
by Mark Wielaard
On architectures (like arm) that don't ALLOW_UNALIGNED there were a
couple more issues with possible unbounded stack usage. The following
3 patches fix those:
libelf: Fix unbounded stack usage in elf_getarsym
libelf: Fix possible unbounded stack usage in getphdr_wrlock.
libelf: Fix possible unbounded stack usage in load_shdr_wrlock.
8 years, 10 months
Fix gcc -fsanitize=nonnull-attribute issues
by Mark Wielaard
GCC 5.1 includes -fsanitize=nonnull-attribute in -fsanitize=undefined.
This showed a couple of places where we were passing a NULL argument
to functions not expecting them. Even though these functions might not
actually use the argument (if for example the size argument of a buffer
is zero), gcc might use the information to assume the passed in variables
are always nonnull, which might cause unexpected optimizations.
libdwfl: Check file_name is not NULL before calling canonicalize_file_name.
libelf: Don't call mempcpy with possible NULL d_buf.
libelf: Don't call memmove with possible NULL buffer.
elfcmp: Don't call memcmp with possible NULL d_buf.
8 years, 10 months
[PATCH] tests: Always print reason when skipping test.
by Mark Wielaard
Make sure the reason a test is SKIPPED is added to the test-suite.log.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
tests/ChangeLog | 13 +++++++++++++
tests/backtrace-subr.sh | 4 ++--
tests/run-addr2line-i-demangle-test.sh | 1 +
tests/run-backtrace-demangle.sh | 3 ++-
tests/run-backtrace-native-biarch.sh | 3 ++-
tests/run-backtrace-native-core-biarch.sh | 3 ++-
tests/run-stack-demangled-test.sh | 1 +
tests/test-subr.sh | 4 ++--
8 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 94ee1f7..19878ac 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,16 @@
+2015-05-30 Mark Wielaard <mjw(a)redhat.com>
+
+ * backtrace-subr.sh (check_native_core): Notice core file couldn't be
+ generated before skipping.
+ * run-addr2line-i-demangle-test.sh: Notice demangler is unsupported
+ before skipping.
+ * run-backtrace-demangle.sh: Likewise.
+ * run-stack-demangled-test.sh: Likewise.
+ * run-backtrace-native-biarch.sh: Notice biarch testing is disabled
+ before skipping.
+ * run-backtrace-native-core-biarch.sh: Likewise.
+ * test-subr.sh (testfiles): Notice how bunzip2 fails before skipping.
+
2015-05-20 Mark Wielaard <mjw(a)redhat.com>
* run-addr2line-i-test.sh: Add pretty test.
diff --git a/tests/backtrace-subr.sh b/tests/backtrace-subr.sh
index f04721c..790b4f4 100644
--- a/tests/backtrace-subr.sh
+++ b/tests/backtrace-subr.sh
@@ -1,4 +1,4 @@
-# Copyright (C) 2013 Red Hat, Inc.
+# Copyright (C) 2013, 2015 Red Hat, Inc.
# This file is part of elfutils.
#
# This file is free software; you can redistribute it and/or modify
@@ -135,7 +135,7 @@ check_native_core()
if [ -f core ]; then
mv core "$core"
fi
- if [ ! -f "$core" ]; then exit 77; fi
+ if [ ! -f "$core" ]; then echo "No $core file generated"; exit 77; fi
if [ "x$SAVED_VALGRIND_CMD" != "x" ]; then
VALGRIND_CMD="$SAVED_VALGRIND_CMD"
diff --git a/tests/run-addr2line-i-demangle-test.sh b/tests/run-addr2line-i-demangle-test.sh
index e709acf..1af8562 100755
--- a/tests/run-addr2line-i-demangle-test.sh
+++ b/tests/run-addr2line-i-demangle-test.sh
@@ -16,6 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
if test -n "$ELFUTILS_DISABLE_DEMANGLE"; then
+ echo "demangler unsupported"
exit 77
fi
diff --git a/tests/run-backtrace-demangle.sh b/tests/run-backtrace-demangle.sh
index 6e18e77..71a7351 100755
--- a/tests/run-backtrace-demangle.sh
+++ b/tests/run-backtrace-demangle.sh
@@ -1,5 +1,5 @@
#! /bin/bash
-# Copyright (C) 2014 Red Hat, Inc.
+# Copyright (C) 2014, 2015 Red Hat, Inc.
# This file is part of elfutils.
#
# This file is free software; you can redistribute it and/or modify
@@ -16,6 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
if test -n "$ELFUTILS_DISABLE_DEMANGLE"; then
+ echo "demangler unsupported"
exit 77
fi
diff --git a/tests/run-backtrace-native-biarch.sh b/tests/run-backtrace-native-biarch.sh
index 3a407c8..2afe38a 100755
--- a/tests/run-backtrace-native-biarch.sh
+++ b/tests/run-backtrace-native-biarch.sh
@@ -1,5 +1,5 @@
#! /bin/bash
-# Copyright (C) 2013 Red Hat, Inc.
+# Copyright (C) 2013, 2015 Red Hat, Inc.
# This file is part of elfutils.
#
# This file is free software; you can redistribute it and/or modify
@@ -16,6 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
if test -n "$ELFUTILS_DISABLE_BIARCH"; then
+ echo "biarch testing disabled"
exit 77
fi
diff --git a/tests/run-backtrace-native-core-biarch.sh b/tests/run-backtrace-native-core-biarch.sh
index fbd8025..02552ce 100755
--- a/tests/run-backtrace-native-core-biarch.sh
+++ b/tests/run-backtrace-native-core-biarch.sh
@@ -1,5 +1,5 @@
#! /bin/bash
-# Copyright (C) 2013 Red Hat, Inc.
+# Copyright (C) 2013, 2015 Red Hat, Inc.
# This file is part of elfutils.
#
# This file is free software; you can redistribute it and/or modify
@@ -16,6 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
if test -n "$ELFUTILS_DISABLE_BIARCH"; then
+ echo "biarch testing disabled"
exit 77
fi
diff --git a/tests/run-stack-demangled-test.sh b/tests/run-stack-demangled-test.sh
index 0d9f8f3..98f8ff8 100755
--- a/tests/run-stack-demangled-test.sh
+++ b/tests/run-stack-demangled-test.sh
@@ -16,6 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
if test -n "$ELFUTILS_DISABLE_DEMANGLE"; then
+ echo "demangler unsupported"
exit 77
fi
diff --git a/tests/test-subr.sh b/tests/test-subr.sh
index 5e796b4..f397aed 100644
--- a/tests/test-subr.sh
+++ b/tests/test-subr.sh
@@ -1,5 +1,5 @@
#! /bin/sh
-# Copyright (C) 2005-2014 Red Hat, Inc.
+# Copyright (C) 2005-2015 Red Hat, Inc.
# This file is part of elfutils.
#
# This file is free software; you can redistribute it and/or modify
@@ -47,7 +47,7 @@ tempfiles()
testfiles()
{
for file; do
- bunzip2 -c ${abs_srcdir}/${file}.bz2 > ${file} 2>/dev/null || exit 77
+ bunzip2 -c ${abs_srcdir}/${file}.bz2 > ${file} || exit 77
remove_files="$remove_files $file"
done
}
--
2.1.0
8 years, 10 months
[PATCH] configure: Add check for bunzip2 and maintainer-mode tools.
by Mark Wielaard
Without bunzip2 make check cannot be run. To generate all files in
maintainer-mode flex and bison are needed. Otherwise check that
libdw/known-dwarf.h is already generated.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
ChangeLog | 6 ++++++
configure.ac | 24 ++++++++++++++++++++++++
2 files changed, 30 insertions(+)
diff --git a/ChangeLog b/ChangeLog
index 9d417f9..f281f98 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2015-05-30 Mark Wielaard <mjw(a)redhat.com>
+
+ * configure.ac: Check for bunzip2. Check flex and bison are
+ installed in maintainer-mode. Otherwise check libdw/known-dwarf.h
+ is already generated.
+
2015-05-21 Mark Wielaard <mjw(a)redhat.com>
* configure.ac: Add --enable-sanitize-undefined.
diff --git a/configure.ac b/configure.ac
index e0adad7..6386e96 100644
--- a/configure.ac
+++ b/configure.ac
@@ -404,6 +404,29 @@ utrace_BIARCH
CC_BIARCH="$CC $utrace_biarch"
AC_SUBST([CC_BIARCH])
+# In maintainer mode we really need flex and bison.
+# Otherwise we really need a release dir with maintainer files generated.
+if test "x$enable_maintainer_mode" = xyes; then
+ AC_CHECK_PROG(HAVE_FLEX, flex, yes, no)
+ if test "$HAVE_FLEX" = "no"; then
+ AC_MSG_ERROR([flex needed in maintainer mode])
+ fi
+ AC_CHECK_PROG(HAVE_BISON, bison, yes, no)
+ if test "$HAVE_BISON" = "no"; then
+ AC_MSG_ERROR([bison needed in maintainer mode])
+ fi
+else
+ if test ! -f ${srcdir}/libdw/known-dwarf.h; then
+ AC_MSG_ERROR([No libdw/known-dwarf.h. configure --enable-maintainer-mode])
+ fi
+fi
+
+# The testfiles are all compressed, we need bunzip2 when running make check
+AC_CHECK_PROG(HAVE_BUNZIP2, bunzip2, yes, no)
+if test "$HAVE_BUNZIP2" = "no"; then
+ AC_MSG_WARN([No bunzip2, needed to run make check])
+fi
+
AC_OUTPUT
AC_MSG_NOTICE([
@@ -434,6 +457,7 @@ AC_MSG_NOTICE([
Native language support : ${USE_NLS}
EXTRA TEST FEATURES (used with make check)
+ have bunzip2 installed (required) : ${HAVE_BUNZIP2}
debug branch prediction : ${use_debugpred}
gprof support : ${use_gprof}
gcov support : ${use_gcov}
--
2.1.0
8 years, 10 months
[PATCH] libelf: Split checks for ehdr and shdr, drop phdr check in file_read_elf.
by Mark Wielaard
There are various places in the code that check whether mmapped structures
are correctly aligned (or ALLOW_UNALIGNED is set). Some of these checks
are asserts. Like the one in elf(32|64)_getshdr. We should not get into
that part of the code if the shdr scn structure was cached in elf_begin
because it was mmapped in and properly aligned.
These asserts could trigger because in elf_begin.c file_read_elf ()
all alignment checks were combined. So even though only one of the ehdr,
shdr or phdr structures were not properly aligned all structures would be
copied. Also the phdr structure was not even read in elf_begin, so the
alignment check was unnecessary.
This patch splits the alignment checks and reading of ehdr and shdr
structures into separate code paths. It also drops the phdr alignment
checks in elf_begin. Those phdr checks are done in elf(32|64)_getphdr
already.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libelf/ChangeLog | 5 ++
libelf/elf_begin.c | 140 ++++++++++++++++++++++++++++-------------------------
2 files changed, 80 insertions(+), 65 deletions(-)
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 79308fe..fd2fc53 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,8 @@
+2015-06-02 Mark Wielaard <mjw(a)redhat.com>
+
+ * elf_begin.c (file_read_elf): Split checks for ehdr and shdr
+ alignment, drop phdr alignment check.
+
2015-05-31 Mark Wielaard <mjw(a)redhat.com>
* elf32_getshdr.c (load_shdr_wrlock): Allocate shdrs with malloc,
diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c
index ae1e712..e2e3b6b 100644
--- a/libelf/elf_begin.c
+++ b/libelf/elf_begin.c
@@ -1,5 +1,5 @@
/* Create descriptor for processing file.
- Copyright (C) 1998-2010, 2012, 2014 Red Hat, Inc.
+ Copyright (C) 1998-2010, 2012, 2014, 2015 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper(a)redhat.com>, 1998.
@@ -306,17 +306,46 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
/* This is a 32-bit binary. */
if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
&& (ALLOW_UNALIGNED
- || ((((uintptr_t) ehdr) & (__alignof__ (Elf32_Ehdr) - 1)) == 0
- && ((uintptr_t) ((char *) ehdr + ehdr->e_shoff)
- & (__alignof__ (Elf32_Shdr) - 1)) == 0
- && ((uintptr_t) ((char *) ehdr + ehdr->e_phoff)
- & (__alignof__ (Elf32_Phdr) - 1)) == 0)))
+ || (((uintptr_t) ehdr) & (__alignof__ (Elf32_Ehdr) - 1)) == 0))
{
/* We can use the mmapped memory. */
elf->state.elf32.ehdr = ehdr;
+ }
+ else
+ {
+ /* Copy the ELF header. */
+ elf->state.elf32.ehdr = memcpy (&elf->state.elf32.ehdr_mem, e_ident,
+ sizeof (Elf32_Ehdr));
+
+ if (e_ident[EI_DATA] != MY_ELFDATA)
+ {
+ CONVERT (elf->state.elf32.ehdr_mem.e_type);
+ CONVERT (elf->state.elf32.ehdr_mem.e_machine);
+ CONVERT (elf->state.elf32.ehdr_mem.e_version);
+ CONVERT (elf->state.elf32.ehdr_mem.e_entry);
+ CONVERT (elf->state.elf32.ehdr_mem.e_phoff);
+ CONVERT (elf->state.elf32.ehdr_mem.e_shoff);
+ CONVERT (elf->state.elf32.ehdr_mem.e_flags);
+ CONVERT (elf->state.elf32.ehdr_mem.e_ehsize);
+ CONVERT (elf->state.elf32.ehdr_mem.e_phentsize);
+ CONVERT (elf->state.elf32.ehdr_mem.e_phnum);
+ CONVERT (elf->state.elf32.ehdr_mem.e_shentsize);
+ CONVERT (elf->state.elf32.ehdr_mem.e_shnum);
+ CONVERT (elf->state.elf32.ehdr_mem.e_shstrndx);
+ }
+ }
+
+ /* Don't precache the phdr pointer here.
+ elf32_getphdr will validate it against the size when asked. */
- if (unlikely (ehdr->e_shoff >= maxsize)
- || unlikely (maxsize - ehdr->e_shoff
+ Elf32_Off e_shoff = elf->state.elf32.ehdr->e_shoff;
+ if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
+ && (ALLOW_UNALIGNED
+ || (((uintptr_t) ((char *) ehdr + e_shoff)
+ & (__alignof__ (Elf32_Shdr) - 1)) == 0)))
+ {
+ if (unlikely (e_shoff >= maxsize)
+ || unlikely (maxsize - e_shoff
< scncnt * sizeof (Elf32_Shdr)))
{
free_and_out:
@@ -325,10 +354,7 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
return NULL;
}
elf->state.elf32.shdr
- = (Elf32_Shdr *) ((char *) ehdr + ehdr->e_shoff);
-
- /* Don't precache the phdr pointer here.
- elf32_getphdr will validate it against the size when asked. */
+ = (Elf32_Shdr *) ((char *) ehdr + e_shoff);
for (size_t cnt = 0; cnt < scncnt; ++cnt)
{
@@ -361,27 +387,6 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
}
else
{
- /* Copy the ELF header. */
- elf->state.elf32.ehdr = memcpy (&elf->state.elf32.ehdr_mem, e_ident,
- sizeof (Elf32_Ehdr));
-
- if (e_ident[EI_DATA] != MY_ELFDATA)
- {
- CONVERT (elf->state.elf32.ehdr_mem.e_type);
- CONVERT (elf->state.elf32.ehdr_mem.e_machine);
- CONVERT (elf->state.elf32.ehdr_mem.e_version);
- CONVERT (elf->state.elf32.ehdr_mem.e_entry);
- CONVERT (elf->state.elf32.ehdr_mem.e_phoff);
- CONVERT (elf->state.elf32.ehdr_mem.e_shoff);
- CONVERT (elf->state.elf32.ehdr_mem.e_flags);
- CONVERT (elf->state.elf32.ehdr_mem.e_ehsize);
- CONVERT (elf->state.elf32.ehdr_mem.e_phentsize);
- CONVERT (elf->state.elf32.ehdr_mem.e_phnum);
- CONVERT (elf->state.elf32.ehdr_mem.e_shentsize);
- CONVERT (elf->state.elf32.ehdr_mem.e_shnum);
- CONVERT (elf->state.elf32.ehdr_mem.e_shstrndx);
- }
-
for (size_t cnt = 0; cnt < scncnt; ++cnt)
{
elf->state.elf32.scns.data[cnt].index = cnt;
@@ -402,24 +407,50 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
/* This is a 64-bit binary. */
if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
&& (ALLOW_UNALIGNED
- || ((((uintptr_t) ehdr) & (__alignof__ (Elf64_Ehdr) - 1)) == 0
- && ((uintptr_t) ((char *) ehdr + ehdr->e_shoff)
- & (__alignof__ (Elf64_Shdr) - 1)) == 0
- && ((uintptr_t) ((char *) ehdr + ehdr->e_phoff)
- & (__alignof__ (Elf64_Phdr) - 1)) == 0)))
+ || (((uintptr_t) ehdr) & (__alignof__ (Elf64_Ehdr) - 1)) == 0))
{
/* We can use the mmapped memory. */
elf->state.elf64.ehdr = ehdr;
+ }
+ else
+ {
+ /* Copy the ELF header. */
+ elf->state.elf64.ehdr = memcpy (&elf->state.elf64.ehdr_mem, e_ident,
+ sizeof (Elf64_Ehdr));
+
+ if (e_ident[EI_DATA] != MY_ELFDATA)
+ {
+ CONVERT (elf->state.elf64.ehdr_mem.e_type);
+ CONVERT (elf->state.elf64.ehdr_mem.e_machine);
+ CONVERT (elf->state.elf64.ehdr_mem.e_version);
+ CONVERT (elf->state.elf64.ehdr_mem.e_entry);
+ CONVERT (elf->state.elf64.ehdr_mem.e_phoff);
+ CONVERT (elf->state.elf64.ehdr_mem.e_shoff);
+ CONVERT (elf->state.elf64.ehdr_mem.e_flags);
+ CONVERT (elf->state.elf64.ehdr_mem.e_ehsize);
+ CONVERT (elf->state.elf64.ehdr_mem.e_phentsize);
+ CONVERT (elf->state.elf64.ehdr_mem.e_phnum);
+ CONVERT (elf->state.elf64.ehdr_mem.e_shentsize);
+ CONVERT (elf->state.elf64.ehdr_mem.e_shnum);
+ CONVERT (elf->state.elf64.ehdr_mem.e_shstrndx);
+ }
+ }
+
+ /* Don't precache the phdr pointer here.
+ elf64_getphdr will validate it against the size when asked. */
- if (unlikely (ehdr->e_shoff >= maxsize)
- || unlikely (maxsize - ehdr->e_shoff
+ Elf64_Off e_shoff = elf->state.elf64.ehdr->e_shoff;
+ if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
+ && (ALLOW_UNALIGNED
+ || (((uintptr_t) ((char *) ehdr + e_shoff)
+ & (__alignof__ (Elf64_Shdr) - 1)) == 0)))
+ {
+ if (unlikely (e_shoff >= maxsize)
+ || unlikely (maxsize - e_shoff
< scncnt * sizeof (Elf64_Shdr)))
goto free_and_out;
elf->state.elf64.shdr
- = (Elf64_Shdr *) ((char *) ehdr + ehdr->e_shoff);
-
- /* Don't precache the phdr pointer here.
- elf64_getphdr will validate it against the size when asked. */
+ = (Elf64_Shdr *) ((char *) ehdr + e_shoff);
for (size_t cnt = 0; cnt < scncnt; ++cnt)
{
@@ -452,27 +483,6 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
}
else
{
- /* Copy the ELF header. */
- elf->state.elf64.ehdr = memcpy (&elf->state.elf64.ehdr_mem, e_ident,
- sizeof (Elf64_Ehdr));
-
- if (e_ident[EI_DATA] != MY_ELFDATA)
- {
- CONVERT (elf->state.elf64.ehdr_mem.e_type);
- CONVERT (elf->state.elf64.ehdr_mem.e_machine);
- CONVERT (elf->state.elf64.ehdr_mem.e_version);
- CONVERT (elf->state.elf64.ehdr_mem.e_entry);
- CONVERT (elf->state.elf64.ehdr_mem.e_phoff);
- CONVERT (elf->state.elf64.ehdr_mem.e_shoff);
- CONVERT (elf->state.elf64.ehdr_mem.e_flags);
- CONVERT (elf->state.elf64.ehdr_mem.e_ehsize);
- CONVERT (elf->state.elf64.ehdr_mem.e_phentsize);
- CONVERT (elf->state.elf64.ehdr_mem.e_phnum);
- CONVERT (elf->state.elf64.ehdr_mem.e_shentsize);
- CONVERT (elf->state.elf64.ehdr_mem.e_shnum);
- CONVERT (elf->state.elf64.ehdr_mem.e_shstrndx);
- }
-
for (size_t cnt = 0; cnt < scncnt; ++cnt)
{
elf->state.elf64.scns.data[cnt].index = cnt;
--
1.8.3.1
8 years, 11 months
[PATCH] libdw: Fix overflow in read_encoded_value for the DW_EH_PE_indirect case.
by Mark Wielaard
If we are going to dereference a pointer there should be at least enough
data to hold a pointer. Found by afl-fuzz.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdw/ChangeLog | 5 +++++
libdw/encoded-value.h | 7 ++++---
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 2757093..aa4d09c 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2015-05-27 Mark Wielaard <mjw(a)redhat.com>
+
+ * encoded-value.h (read_encoded_value): Check data d_size contains
+ at least enough data to hold a pointer for DW_EH_PE_indirect.
+
2015-05-22 Mark Wielaard <mjw(a)redhat.com>
* dwarf_getsrclines.c (read_srclines): Limit stack usage of lines
diff --git a/libdw/encoded-value.h b/libdw/encoded-value.h
index 0fa2018..48d868f 100644
--- a/libdw/encoded-value.h
+++ b/libdw/encoded-value.h
@@ -214,9 +214,10 @@ read_encoded_value (const Dwarf_CFI *cache, uint8_t encoding,
if (unlikely (*result < cache->frame_vaddr))
return true;
*result -= cache->frame_vaddr;
- if (unlikely (*result > (cache->data->d.d_size
- - encoded_value_size (NULL, cache->e_ident,
- DW_EH_PE_absptr, NULL))))
+ size_t ptrsize = encoded_value_size (NULL, cache->e_ident,
+ DW_EH_PE_absptr, NULL);
+ if (unlikely (cache->data->d.d_size < ptrsize
+ || *result > (cache->data->d.d_size - ptrsize)))
return true;
const uint8_t *ptr = cache->data->d.d_buf + *result;
if (unlikely (__libdw_cfi_read_address_inc (cache, &ptr, 0, result)
--
1.8.3.1
8 years, 11 months