[Bug tools/25082] Multiple crashes in eu-unstrip

2019-10-21 Thread mark at klomp dot org
https://sourceware.org/bugzilla/show_bug.cgi?id=25082

Mark Wielaard  changed:

   What|Removed |Added

 Status|UNCONFIRMED |ASSIGNED
   Last reconfirmed||2019-10-21
 CC||mark at klomp dot org
   Assignee|unassigned at sourceware dot org   |mark at klomp dot org
 Ever confirmed|0   |1

--- Comment #3 from Mark Wielaard  ---
Created attachment 12047
  --> https://sourceware.org/bugzilla/attachment.cgi?id=12047&action=edit
unstrip: Add various checks for bad input data

eu-unstrip was clearly not written for bad ELF input files. Not surprisingly
because it would be slightly odd to run it on untrusted input, which wasn't
just stripped in two.

But I have added a couple of robustness fixed that should at least not make it
crash and give an error message that will hopefully explain what is wrong with
the input files.

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

Re: [PATCH 2/3] libdw: Rewrite the memory handler to be thread-safe.

2019-10-21 Thread Mark Wielaard
Hi,

Finally back to this patch series.

On Thu, 2019-08-29 at 15:16 +0200, Mark Wielaard wrote:
> diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
> index 29795c10..fc573cb3 100644
> --- a/libdw/dwarf_end.c
> +++ b/libdw/dwarf_end.c
> @@ -94,14 +94,15 @@ dwarf_end (Dwarf *dwarf)
>/* And the split Dwarf.  */
>tdestroy (dwarf->split_tree, noop_free);
>  
> -  struct libdw_memblock *memp = dwarf->mem_tail;
> -  /* The first block is allocated together with the Dwarf object.  */
> -  while (memp->prev != NULL)
> +  /* Free the internally allocated memory.  */
> +  struct libdw_memblock *memp = (struct libdw_memblock *)dwarf->mem_tail;
> +  while (memp != NULL)
>   {
> struct libdw_memblock *prevp = memp->prev;
> free (memp);
> memp = prevp;
>   }
> +  pthread_key_delete (dwarf->mem_key);
>  
>/* Free the pubnames helper structure.  */
>free (dwarf->pubnames_sets);

This doesn't build on older GCCs (I am using 4.8.5) with this compile error:


libdw/dwarf_end.c: In function ‘dwarf_end’:
libdw/dwarf_end.c:98:45: error: cannot convert to a pointer type
   struct libdw_memblock *memp = (struct libdw_memblock *)dwarf->mem_tail;
 ^

This is because mem_tail is defined as:

> diff --git a/libdw/libdwP.h b/libdw/libdwP.h
> index eebb7d12..ad2599eb 100644
> --- a/libdw/libdwP.h
> +++ b/libdw/libdwP.h
> @@ -218,16 +231,11 @@ struct Dwarf
>/* Similar for addrx/constx, which will come from .debug_addr section.  */
>struct Dwarf_CU *fake_addr_cu;
>  
> -  /* Internal memory handling.  This is basically a simplified
> - reimplementation of obstacks.  Unfortunately the standard obstack
> - implementation is not usable in libraries.  */
> -  struct libdw_memblock
> -  {
> -size_t size;
> -size_t remaining;
> -struct libdw_memblock *prev;
> -char mem[0];
> -  } *mem_tail;
> +  /* Internal memory handling.  Each thread allocates separately and only
> + allocates from its own blocks, while all the blocks are pushed 
> atomically
> + onto a unified stack for easy deallocation.  */
> +  pthread_key_t mem_key;
> +  atomic_uintptr_t mem_tail;
>  
>/* Default size of allocated memory blocks.  */
>size_t mem_default_size;

And for older compilers, without stdatomic.h, this means atomic_uintptr_t is 
really:

typedef _Atomic(uintptr_t)  atomic_uintptr_t;
#define _Atomic(T)  struct { volatile __typeof__(T) __val; }

And you cannot cast a struct to a pointer type directly.

To make this work on both older and newer gcc versions I changed this to:

diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
index fc573cb3..76ab9954 100644
--- a/libdw/dwarf_end.c
+++ b/libdw/dwarf_end.c
@@ -95,7 +95,8 @@ dwarf_end (Dwarf *dwarf)
   tdestroy (dwarf->split_tree, noop_free);
 
   /* Free the internally allocated memory.  */
-  struct libdw_memblock *memp = (struct libdw_memblock *)dwarf->mem_tail;
+  struct libdw_memblock *memp;
+  memp = (struct libdw_memblock *) atomic_load (&dwarf->mem_tail);
   while (memp != NULL)
{
  struct libdw_memblock *prevp = memp->prev;

Does that look reasonable?

Thanks,

Mark


Re: [PATCH 2/3] libdw: Rewrite the memory handler to be thread-safe.

2019-10-21 Thread Jonathon Anderson




On Mon, Oct 21, 2019 at 18:13, Mark Wielaard  wrote:

Hi,

Finally back to this patch series.

On Thu, 2019-08-29 at 15:16 +0200, Mark Wielaard wrote:

 diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
 index 29795c10..fc573cb3 100644
 --- a/libdw/dwarf_end.c
 +++ b/libdw/dwarf_end.c
 @@ -94,14 +94,15 @@ dwarf_end (Dwarf *dwarf)
/* And the split Dwarf.  */
tdestroy (dwarf->split_tree, noop_free);

 -  struct libdw_memblock *memp = dwarf->mem_tail;
 -  /* The first block is allocated together with the Dwarf 
object.  */

 -  while (memp->prev != NULL)
 +  /* Free the internally allocated memory.  */
 +  struct libdw_memblock *memp = (struct libdw_memblock 
*)dwarf->mem_tail;

 +  while (memp != NULL)
{
  struct libdw_memblock *prevp = memp->prev;
  free (memp);
  memp = prevp;
}
 +  pthread_key_delete (dwarf->mem_key);

/* Free the pubnames helper structure.  */
free (dwarf->pubnames_sets);


This doesn't build on older GCCs (I am using 4.8.5) with this compile 
error:



libdw/dwarf_end.c: In function ‘dwarf_end’:
libdw/dwarf_end.c:98:45: error: cannot convert to a pointer type
   struct libdw_memblock *memp = (struct libdw_memblock 
*)dwarf->mem_tail;

 ^


Ah, whoops. Thanks for catching that one.



This is because mem_tail is defined as:


 diff --git a/libdw/libdwP.h b/libdw/libdwP.h
 index eebb7d12..ad2599eb 100644
 --- a/libdw/libdwP.h
 +++ b/libdw/libdwP.h
 @@ -218,16 +231,11 @@ struct Dwarf
/* Similar for addrx/constx, which will come from .debug_addr 
section.  */

struct Dwarf_CU *fake_addr_cu;

 -  /* Internal memory handling.  This is basically a simplified
 - reimplementation of obstacks.  Unfortunately the standard 
obstack

 - implementation is not usable in libraries.  */
 -  struct libdw_memblock
 -  {
 -size_t size;
 -size_t remaining;
 -struct libdw_memblock *prev;
 -char mem[0];
 -  } *mem_tail;
 +  /* Internal memory handling.  Each thread allocates separately 
and only
 + allocates from its own blocks, while all the blocks are 
pushed atomically

 + onto a unified stack for easy deallocation.  */
 +  pthread_key_t mem_key;
 +  atomic_uintptr_t mem_tail;

/* Default size of allocated memory blocks.  */
size_t mem_default_size;


And for older compilers, without stdatomic.h, this means 
atomic_uintptr_t is really:


typedef _Atomic(uintptr_t)  atomic_uintptr_t;
#define _Atomic(T)  struct { volatile 
__typeof__(T) __val; }


And you cannot cast a struct to a pointer type directly.

To make this work on both older and newer gcc versions I changed this 
to:


diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
index fc573cb3..76ab9954 100644
--- a/libdw/dwarf_end.c
+++ b/libdw/dwarf_end.c
@@ -95,7 +95,8 @@ dwarf_end (Dwarf *dwarf)
   tdestroy (dwarf->split_tree, noop_free);

   /* Free the internally allocated memory.  */
-  struct libdw_memblock *memp = (struct libdw_memblock 
*)dwarf->mem_tail;

+  struct libdw_memblock *memp;
+  memp = (struct libdw_memblock *) atomic_load 
(&dwarf->mem_tail);

   while (memp != NULL)
{
  struct libdw_memblock *prevp = memp->prev;

Does that look reasonable?


It does, although I would prefer:

diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
index 9ca17212..6da9e0cd 100644
--- a/libdw/dwarf_end.c
+++ b/libdw/dwarf_end.c
@@ -95,7 +95,9 @@ dwarf_end (Dwarf *dwarf)
  tdestroy (dwarf->split_tree, noop_free);

  /* Free the internally allocated memory.  */
-  struct libdw_memblock *memp = (struct libdw_memblock 
*)dwarf->mem_tail;

+  struct libdw_memblock *memp;
+  memp  = (struct libdw_memblock *)atomic_load(&dwarf->mem_tail,
+   
memory_order_relaxed);

  while (memp != NULL)
{
  struct libdw_memblock *prevp = memp->prev;

Because some idiot thought making seq_cst the default was a good idea. 
And this way it notes in the code that this load is non-synchronizing.


-Jonathon



Thanks,

Mark




Re: [PATCH 2/3] libdw: Rewrite the memory handler to be thread-safe.

2019-10-21 Thread Mark Wielaard
Hi,

On Mon, 2019-10-21 at 11:28 -0500, Jonathon Anderson wrote:
> On Mon, Oct 21, 2019 at 18:13, Mark Wielaard  wrote:
> > Does that look reasonable?
> 
> It does, although I would prefer:
> 
> diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
> index 9ca17212..6da9e0cd 100644
> --- a/libdw/dwarf_end.c
> +++ b/libdw/dwarf_end.c
> @@ -95,7 +95,9 @@ dwarf_end (Dwarf *dwarf)
>tdestroy (dwarf->split_tree, noop_free);
> 
>/* Free the internally allocated memory.  */
> -  struct libdw_memblock *memp = (struct libdw_memblock 
> *)dwarf->mem_tail;
> +  struct libdw_memblock *memp;
> +  memp  = (struct libdw_memblock *)atomic_load(&dwarf->mem_tail,
> +   memory_order_relaxed);
>while (memp != NULL)
>  {
>struct libdw_memblock *prevp = memp->prev;
> 
> Because some idiot thought making seq_cst the default was a good idea. 
> And this way it notes in the code that this load is non-synchronizing.

Lets avoid the "strong" language about people. But lets see if we can
make the load less "strong" for the atomics :)

I think we cannot use the atomic_load () function, but have to use
atomic_load_explicit. So it would become:

diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
index fc573cb3..a2e94436 100644
--- a/libdw/dwarf_end.c
+++ b/libdw/dwarf_end.c
@@ -95,7 +95,10 @@ dwarf_end (Dwarf *dwarf)
   tdestroy (dwarf->split_tree, noop_free);
 
   /* Free the internally allocated memory.  */
-  struct libdw_memblock *memp = (struct libdw_memblock *)dwarf->mem_tail;
+  struct libdw_memblock *memp;
+  memp = (struct libdw_memblock *) (atomic_load_explicit
+   (&dwarf->mem_tail,
+memory_order_relaxed));
   while (memp != NULL)
{
  struct libdw_memblock *prevp = memp->prev;

Cheers,

Mark


[Bug tools/25077] unstrip bad handling of sh_entsize of the symver section

2019-10-21 Thread mark at klomp dot org
https://sourceware.org/bugzilla/show_bug.cgi?id=25077

Mark Wielaard  changed:

   What|Removed |Added

  Component|libelf  |tools
   Assignee|unassigned at sourceware dot org   |mark at klomp dot org
Summary|AddressSanitizer:   |unstrip bad handling of
   |heap-buffer-overflow at |sh_entsize of the symver
   |libelf/elf32_updatefile.c:7 |section
   |72  |

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

[Bug tools/25083] unstrip tries to write out an enormous amount of data

2019-10-21 Thread mark at klomp dot org
https://sourceware.org/bugzilla/show_bug.cgi?id=25083

Mark Wielaard  changed:

   What|Removed |Added

  Component|libelf  |tools
   Assignee|unassigned at sourceware dot org   |mark at klomp dot org
Summary|Unexpected hangs at |unstrip tries to write out
   |elf32_updatefile.c:518  |an enormous amount of data

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

[Bug tools/25077] unstrip bad handling of sh_entsize of the symver section

2019-10-21 Thread leftcopy.chx at gmail dot com
https://sourceware.org/bugzilla/show_bug.cgi?id=25077

--- Comment #2 from leftcopy.chx at gmail dot com ---
Since this crashes occurs when calling `elf_update`, which resides in libelf, I
suppose this is a libelf library issue.

I'd suggest adding some documents to warn that it is the developers' duty to
ensure that the claimed symver size matches with the actual one, or better
resolves the size purely inside libelf code?

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