[PATCHv1 1/2] libdwfl: specify optional sysroot to search for shared libraries

2019-01-20 Thread Luke Diamand
When searching the list of modules in a core file, if the core was
generated on a different system to the current one, we need to look
in a sysroot for the various shared objects.

For example, we might be looking at a core file from an ARM system
using elfutils running on an x86 host.

This change adds a new function, dwfl_set_sysroot(), which then
gets used when searching for libraries.

Signed-off-by: Luke Diamand 
---
 libdw/libdw.map|  7 ++-
 libdwfl/libdwfl.h  |  5 +
 libdwfl/libdwflP.h |  1 +
 libdwfl/link_map.c | 25 +++--
 4 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/libdw/libdw.map b/libdw/libdw.map
index 55482d58..43a9de2e 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -360,4 +360,9 @@ ELFUTILS_0.173 {
 ELFUTILS_0.175 {
   global:
 dwelf_elf_begin;
-} ELFUTILS_0.173;
\ No newline at end of file
+} ELFUTILS_0.173;
+
+ELFUTILS_0.176 {
+  global:
+dwfl_set_sysroot;
+} ELFUTILS_0.175;
diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h
index a0c1d357..c11e2f24 100644
--- a/libdwfl/libdwfl.h
+++ b/libdwfl/libdwfl.h
@@ -807,6 +807,11 @@ int dwfl_getthread_frames (Dwfl *dwfl, pid_t tid,
 bool dwfl_frame_pc (Dwfl_Frame *state, Dwarf_Addr *pc, bool *isactivation)
   __nonnull_attribute__ (1, 2);
 
+/* Set the sysroot to use when searching for shared libraries. If not
+ specified, search in the system root.  */
+void dwfl_set_sysroot (Dwfl *dwfl, const char *sysroot)
+  __nonnull_attribute__ (1);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
index 941a8b66..993a0e7c 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -138,6 +138,7 @@ struct Dwfl
   int lookup_tail_ndx;
 
   struct Dwfl_User_Core *user_core;
+  const char *sysroot; /* sysroot, or NULL to search standard system paths */
 };
 
 #define OFFLINE_REDZONE0x1
diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c
index 29307c74..0fae680d 100644
--- a/libdwfl/link_map.c
+++ b/libdwfl/link_map.c
@@ -388,8 +388,21 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t 
elfdata,
   if (name != NULL)
{
  /* This code is mostly inlined dwfl_report_elf.  */
- // XXX hook for sysroot
- int fd = open (name, O_RDONLY);
+ char *path_name;
+ const char *sysroot = dwfl->sysroot;
+ int rc;
+
+ /* don't look in the sysroot if the path is already inside the 
sysroot */
+ bool name_in_sysroot = strncmp(name, sysroot, strlen(sysroot)) == 0;
+
+ if (!name_in_sysroot && sysroot)
+   rc = asprintf(&path_name, "%s/%s", sysroot, name);
+ else
+   rc = asprintf(&path_name, "%s", name);
+ if (unlikely(rc == -1))
+   return release_buffer(-1);
+
+ int fd = open (path_name, O_RDONLY);
  if (fd >= 0)
{
  Elf *elf;
@@ -471,6 +484,7 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
close (fd);
}
}
+  free(path_name);
}
 
   if (mod != NULL)
@@ -1037,3 +1051,10 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, 
size_t auxv_size,
 &integrated_memory_callback, &mcb, r_debug_info);
 }
 INTDEF (dwfl_link_map_report)
+
+void
+dwfl_set_sysroot (Dwfl *dwfl, const char *sysroot)
+{
+  dwfl->sysroot = sysroot;
+}
+INTDEF (dwfl_set_sysroot)
-- 
2.20.1



[PATCHv1 2/2] eu-stack: add support for sysroot option

2019-01-20 Thread Luke Diamand
Use the dwfl_set_sysroot() function to set the sysroot to be
used when analysing a core:

e.g.
   $ eu-stack --core core --sysroot /path/to/sysroot -e crashing_prog

Signed-off-by: Luke Diamand 
---
 src/stack.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/src/stack.c b/src/stack.c
index c5f347e1..5a58cc1b 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -73,6 +73,7 @@ static int core_fd = -1;
 static Elf *core = NULL;
 static const char *exec = NULL;
 static char *debuginfo_path = NULL;
+static const char *sysroot = NULL;
 
 static const Dwfl_Callbacks proc_callbacks =
   {
@@ -554,6 +555,10 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
   show_modules = true;
   break;
 
+case 'S':
+  sysroot = arg;
+  break;
+
 case ARGP_KEY_END:
   if (core == NULL && exec != NULL)
argp_error (state,
@@ -587,6 +592,8 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
  dwfl = dwfl_begin (&core_callbacks);
  if (dwfl == NULL)
error (EXIT_BAD, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
+  if (sysroot)
+dwfl_set_sysroot(dwfl, sysroot);
  if (dwfl_core_file_report (dwfl, core, exec) < 0)
error (EXIT_BAD, 0, "dwfl_core_file_report: %s", dwfl_errmsg (-1));
}
@@ -670,6 +677,8 @@ main (int argc, char **argv)
N_("Show at most MAXFRAMES per thread (default 256, use 0 for 
unlimited)"), 0 },
   { "list-modules", 'l', NULL, 0,
N_("Show module memory map with build-id, elf and debug files 
detected"), 0 },
+  { "sysroot", 'S', "sysroot", 0,
+   N_("Set the sysroot to search for libraries referenced from the core 
file"), 0 },
   { NULL, 0, NULL, 0, NULL, 0 }
 };
 
-- 
2.20.1



[PATCHv1 0/2] specify a sysroot to search when examining a core file

2019-01-20 Thread Luke Diamand
Following on from this discussion:
https://sourceware.org/ml/elfutils-devel/2018-q4/msg00224.html

This patch adds a new API to specify a sysroot, and extends eu-stack to
use it with a new command line option.

I have been experimenting with this on various ARM-based platforms,
currently using a virt-qemu platform built from buildroot.

Luke Diamand (2):
  libdwfl: specify optional sysroot to search for shared libraries
  eu-stack: add support for sysroot option

 libdw/libdw.map|  7 ++-
 libdwfl/libdwfl.h  |  5 +
 libdwfl/libdwflP.h |  1 +
 libdwfl/link_map.c | 25 +++--
 src/stack.c|  9 +
 5 files changed, 44 insertions(+), 3 deletions(-)

-- 
2.20.1



MIPS Elfutils support?

2019-01-20 Thread Luke Diamand
Hi!

I was hoping to use elfutils on some MIPS core files. So I was wondering what 
the status is?

There is a patch in Debian (apparently originally from RedHat?) here:

https://sources.debian.org/src/elfutils/0.175-2/debian/patches/mips_backend.diff/

That's not in the mainline code though, and also lacks unwind support (?).

I also have a small patch needed to pick up the shared library process map - 
instead of using DT_DEBUG, MIPS targets use DT_MIPS_RLD_MAP in core files.

Thanks
Luke


[PATCH] libdw: Check terminating NUL byte in dwarf_getsrclines for dir/file table.

2019-01-20 Thread Mark Wielaard
For DWARF version < 5 the .debug_line directory and file tables consist
of a terminating NUL byte after all strings. The code used to just skip
this without checking it actually existed. This could case a spurious
read past the end of data.

Fix the same issue in readelf.

https://sourceware.org/bugzilla/show_bug.cgi?id=24102

Signed-off-by: Mark Wielaard 
---
 libdw/ChangeLog   |  5 +
 libdw/dwarf_getsrclines.c | 11 ---
 src/ChangeLog |  5 +
 src/readelf.c |  8 ++--
 4 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 44405d75e..ff3880df1 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2019-01-20  Mark Wielaard  
+
+   * dwarf_getsrclines.c (read_srclines): Check terminating NUL byte
+   for dir and file lists.
+
 2018-10-23  Mark Wielaard  
 
* dwarf_child.c (__libdw_find_attr): Initialize readp to NULL.
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index 1432b1db7..75ec9c791 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -315,7 +315,7 @@ read_srclines (Dwarf *dbg,
   if (version < 5)
 {
   const unsigned char *dirp = linep;
-  while (*dirp != 0)
+  while (dirp < lineendp && *dirp != 0)
{
  uint8_t *endp = memchr (dirp, '\0', lineendp - dirp);
  if (endp == NULL)
@@ -323,6 +323,8 @@ read_srclines (Dwarf *dbg,
  ++ndirs;
  dirp = endp + 1;
}
+  if (dirp >= lineendp || *dirp != '\0')
+   goto invalid_data;
   ndirs = ndirs + 1; /* There is always the "unknown" dir.  */
 }
   else
@@ -392,11 +394,12 @@ read_srclines (Dwarf *dbg,
{
  dirarray[n].dir = (char *) linep;
  uint8_t *endp = memchr (linep, '\0', lineendp - linep);
- assert (endp != NULL);
+ assert (endp != NULL); // Checked above when calculating ndirlist.
  dirarray[n].len = endp - linep;
  linep = endp + 1;
}
   /* Skip the final NUL byte.  */
+  assert (*linep == '\0'); // Checked above when calculating ndirlist.
   ++linep;
 }
   else
@@ -471,7 +474,7 @@ read_srclines (Dwarf *dbg,
 {
   if (unlikely (linep >= lineendp))
goto invalid_data;
-  while (*linep != 0)
+  while (linep < lineendp && *linep != '\0')
{
  struct filelist *new_file = NEW_FILE ();
 
@@ -527,6 +530,8 @@ read_srclines (Dwarf *dbg,
goto invalid_data;
  get_uleb128 (new_file->info.length, linep, lineendp);
}
+  if (linep >= lineendp || *linep != '\0')
+   goto invalid_data;
   /* Skip the final NUL byte.  */
   ++linep;
 }
diff --git a/src/ChangeLog b/src/ChangeLog
index c0455f1cf..4ad12a969 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,8 @@
+2019-01-20  Mark Wielaard  
+
+   * readelf.c (print_debug_line_section): Check terminating NUL byte
+   for dir and file tables.
+
 2019-01-16  Mark Wielaard  
 
* readelf (handle_core_note): Pass desc to ebl_core_note.
diff --git a/src/readelf.c b/src/readelf.c
index 71651e091..6bad3bfe9 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -8444,7 +8444,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, 
GElf_Ehdr *ehdr,
}
   else
{
- while (*linep != 0)
+ while (linep < lineendp && *linep != 0)
{
  unsigned char *endp = memchr (linep, '\0', lineendp - linep);
  if (unlikely (endp == NULL))
@@ -8454,6 +8454,8 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, 
GElf_Ehdr *ehdr,
 
  linep = endp + 1;
}
+ if (linep >= lineendp || *linep != 0)
+   goto invalid_unit;
  /* Skip the final NUL byte.  */
  ++linep;
}
@@ -8523,7 +8525,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, 
GElf_Ehdr *ehdr,
   else
{
  puts (gettext (" Entry Dir   Time  Size  Name"));
- for (unsigned int cnt = 1; *linep != 0; ++cnt)
+ for (unsigned int cnt = 1; linep < lineendp && *linep != 0; ++cnt)
{
  /* First comes the file name.  */
  char *fname = (char *) linep;
@@ -8553,6 +8555,8 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, 
GElf_Ehdr *ehdr,
  printf (" %-5u %-5u %-9u %-9u %s\n",
  cnt, diridx, mtime, fsize, fname);
}
+ if (linep >= lineendp || *linep != '\0')
+   goto invalid_unit;
  /* Skip the final NUL byte.  */
  ++linep;
}
-- 
2.20.1



[Bug libdw/24102] A Heap-buffer-overflow problem was discovered in the function read_srclines in dwarf_getsrclines.c in libdw

2019-01-20 Thread mark at klomp dot org
https://sourceware.org/bugzilla/show_bug.cgi?id=24102

Mark Wielaard  changed:

   What|Removed |Added

 Status|UNCONFIRMED |ASSIGNED
   Last reconfirmed||2019-01-20
 CC||mark at klomp dot org
  Component|backends|libdw
 Ever confirmed|0   |1

--- Comment #3 from Mark Wielaard  ---
Nice find. Replicated using valgrind on the reproducers.

We would assume the dir and file tables were properly terminated by a NUL byte.
But if that wasn't actually there we could read one byte past the end of the
data buffer. A similar issue was in readelf.c (although it is harder to trigger
since readlelf has more sanity checks before it can get to this point).

Proposed fix:
https://sourceware.org/ml/elfutils-devel/2019-q1/msg00068.html

-- 
You are receiving this mail because:
You are on the CC list for the bug.

[PATCH] libdwfl: Sanity check partial core file dyn data read.

2019-01-20 Thread Mark Wielaard
When reading the dyn data from the core file check if we got everything,
or just part of the data.

https://sourceware.org/bugzilla/show_bug.cgi?id=24103

Signed-off-by: Mark Wielaard 
---
 libdwfl/ChangeLog| 5 +
 libdwfl/dwfl_segment_report_module.c | 6 ++
 2 files changed, 11 insertions(+)

diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index c295fa7d6..de45e7f19 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,8 @@
+2019-01-20  Mark Wielaard  
+
+   * dwfl_segment_report_module.c (dwfl_segment_report_module): Check
+   dyn_filesz vs dyn_data_size after read_portion call.
+
 2019-01-16  Mark Wielaard  
 
* linux-core-attach.c (core_next_thread): Pass desc to ebl_core_note.
diff --git a/libdwfl/dwfl_segment_report_module.c 
b/libdwfl/dwfl_segment_report_module.c
index 0d633ffee..f6ad39b3e 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -783,6 +783,12 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const 
char *name,
   if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0
   && ! read_portion (&dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz))
 {
+  /* dyn_data_size will be zero if we got everything from the initial
+ buffer, otherwise it will be the size of the new buffer that
+ could be read.  */
+  if (dyn_data_size != 0)
+   dyn_filesz = dyn_data_size;
+
   void *dyns = malloc (dyn_filesz);
   Elf32_Dyn (*d32)[dyn_filesz / sizeof (Elf32_Dyn)] = dyns;
   Elf64_Dyn (*d64)[dyn_filesz / sizeof (Elf64_Dyn)] = dyns;
-- 
2.20.1



Re: [PATCHv1 1/2] libdwfl: specify optional sysroot to search for shared libraries

2019-01-20 Thread Dmitry V. Levin
On Sun, Jan 20, 2019 at 03:00:45PM +, Luke Diamand wrote:
> When searching the list of modules in a core file, if the core was
> generated on a different system to the current one, we need to look
> in a sysroot for the various shared objects.
> 
> For example, we might be looking at a core file from an ARM system
> using elfutils running on an x86 host.
> 
> This change adds a new function, dwfl_set_sysroot(), which then
> gets used when searching for libraries.
[...]
> --- a/libdwfl/link_map.c
> +++ b/libdwfl/link_map.c
> @@ -388,8 +388,21 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t 
> elfdata,
>if (name != NULL)
>   {
> /* This code is mostly inlined dwfl_report_elf.  */
> -   // XXX hook for sysroot
> -   int fd = open (name, O_RDONLY);
> +   char *path_name;
> +   const char *sysroot = dwfl->sysroot;
> +   int rc;
> +
> +   /* don't look in the sysroot if the path is already inside the 
> sysroot */
> +   bool name_in_sysroot = strncmp(name, sysroot, strlen(sysroot)) == 0;

Is sysroot guaranteed to be non-NULL at this point?
If yes, is sysroot guaranteed to end with "/"?


-- 
ldv


signature.asc
Description: PGP signature


[Bug libdw/24103] Invalid address Deference in elf64_xlatetom in elf32_xlatetom.c in libelf

2019-01-20 Thread mark at klomp dot org
https://sourceware.org/bugzilla/show_bug.cgi?id=24103

Mark Wielaard  changed:

   What|Removed |Added

 Status|UNCONFIRMED |ASSIGNED
   Last reconfirmed||2019-01-20
 CC||mark at klomp dot org
  Component|libelf  |libdw
 Ever confirmed|0   |1

--- Comment #2 from Mark Wielaard  ---
Thanks. Replicated under valgrind.
This is similar to https://sourceware.org/bugzilla/show_bug.cgi?id=23752

We need to check if we got all the dynamic data we expected from the file.
Proposed patch:
https://sourceware.org/ml/elfutils-devel/2019-q1/msg00070.html

-- 
You are receiving this mail because:
You are on the CC list for the bug.