public inbox for elfutils@sourceware.org
 help / color / mirror / Atom feed
* Noop round trip through elf_update() causes segfaults
@ 2023-12-28  2:40 Daniel Xu
  2023-12-30 17:41 ` Mark Wielaard
  0 siblings, 1 reply; 3+ messages in thread
From: Daniel Xu @ 2023-12-28  2:40 UTC (permalink / raw)
  To: elfutils-devel

Hi,

I was working on code that adds an ELF section containing custom
metadata to ELF binaries when I started getting odd segfaults
in the added-to binary.

I've managed to create a minimal reproducer with a couple interesting
discoveries. The reproducer is available here:

        https://github.com/danobi/elf-segfault

Basically it does a noop round trip between elf_begin() and elf_update().
But the resulting binary, when run, outputs:

        $ ./testprog_copy
        fish: Job 1, './testprog_copy' terminated by signal SIGSEGV (Address boundary error)

Furthermore, I built and ran tests/addsections.c [0] against my testbinary
and I still get:

        $ ./testprog_copy_elfutils
        fish: Job 1, './testprog_copy_elfutils' terminated by signal SIGSEGV (Address boundary error)
 
I've also tried linking against upstream libelf built from source
with the same results.

This leads me to believe I'm doing something very wrong or
I'm hitting a bug.

If it's helps, I'm using elfutils on archlinux with the following
package information:

        $ pacman -Qi libelf
        Name            : libelf
        Version         : 0.190-1
        Description     : Handle ELF object files and DWARF debugging information (libraries)
        Architecture    : x86_64
        URL             : https://sourceware.org/elfutils/
        [...]

[0]: https://sourceware.org/git/?p=elfutils.git;a=blob;f=tests/addsections.c;hb=HEAD

Thanks,
Daniel

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Noop round trip through elf_update() causes segfaults
  2023-12-28  2:40 Noop round trip through elf_update() causes segfaults Daniel Xu
@ 2023-12-30 17:41 ` Mark Wielaard
  2023-12-31  5:16   ` Daniel Xu
  0 siblings, 1 reply; 3+ messages in thread
From: Mark Wielaard @ 2023-12-30 17:41 UTC (permalink / raw)
  To: Daniel Xu; +Cc: elfutils-devel

Hi Daniel,

On Wed, Dec 27, 2023 at 08:40:09PM -0600, Daniel Xu wrote:
> I was working on code that adds an ELF section containing custom
> metadata to ELF binaries when I started getting odd segfaults
> in the added-to binary.
> 
> I've managed to create a minimal reproducer with a couple interesting
> discoveries. The reproducer is available here:
> 
>         https://github.com/danobi/elf-segfault
> 
> Basically it does a noop round trip between elf_begin() and elf_update().
> But the resulting binary, when run, outputs:
> 
>         $ ./testprog_copy
>         fish: Job 1, './testprog_copy' terminated by signal SIGSEGV (Address boundary error)
> 
> Furthermore, I built and ran tests/addsections.c [0] against my testbinary
> and I still get:
> 
>         $ ./testprog_copy_elfutils
>         fish: Job 1, './testprog_copy_elfutils' terminated by signal SIGSEGV (Address boundary error)
>  
> I've also tried linking against upstream libelf built from source
> with the same results.
> 
> This leads me to believe I'm doing something very wrong or
> I'm hitting a bug.

You aren't doing something very wrong, but libelf does something you
aren't expecting. When you are calling elf_update () it will rearrange
the elf sections making sure there are no unnecessary gaps between the
sections in the file, that alignment is correct, etc.

libelf only cares about the section headers. It doesn't know/care
about the program headers. The program headers describe how the
segments have to be loaded at runtime. Since some data has moved
around the program data isn't loaded correctly anymore which causes
the crash.

To prevent libelf from doing this, and take responsibility of how the
sections are layed out yourself you have to call:

  elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT);

Before calling elf_update. Note that in that case you are responsible
for setting/updating the sh_offset fields of the Shdrs yourself.

See for example the elfutils src/elfcompress.c program to see what it
does in case the Elf file has program headers.

Hope that helps,

Mark

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Noop round trip through elf_update() causes segfaults
  2023-12-30 17:41 ` Mark Wielaard
@ 2023-12-31  5:16   ` Daniel Xu
  0 siblings, 0 replies; 3+ messages in thread
From: Daniel Xu @ 2023-12-31  5:16 UTC (permalink / raw)
  To: Mark Wielaard; +Cc: elfutils-devel

Hi Mark,

On Sat, Dec 30, 2023, at 11:41 AM, Mark Wielaard wrote:
> Hi Daniel,
>
> On Wed, Dec 27, 2023 at 08:40:09PM -0600, Daniel Xu wrote:
>> I was working on code that adds an ELF section containing custom
>> metadata to ELF binaries when I started getting odd segfaults
>> in the added-to binary.
>> 
>> I've managed to create a minimal reproducer with a couple interesting
>> discoveries. The reproducer is available here:
>> 
>>         https://github.com/danobi/elf-segfault
>> 
>> Basically it does a noop round trip between elf_begin() and elf_update().
>> But the resulting binary, when run, outputs:
>> 
>>         $ ./testprog_copy
>>         fish: Job 1, './testprog_copy' terminated by signal SIGSEGV (Address boundary error)
>> 
>> Furthermore, I built and ran tests/addsections.c [0] against my testbinary
>> and I still get:
>> 
>>         $ ./testprog_copy_elfutils
>>         fish: Job 1, './testprog_copy_elfutils' terminated by signal SIGSEGV (Address boundary error)
>>  
>> I've also tried linking against upstream libelf built from source
>> with the same results.
>> 
>> This leads me to believe I'm doing something very wrong or
>> I'm hitting a bug.
>
> You aren't doing something very wrong, but libelf does something you
> aren't expecting. When you are calling elf_update () it will rearrange
> the elf sections making sure there are no unnecessary gaps between the
> sections in the file, that alignment is correct, etc.
>
> libelf only cares about the section headers. It doesn't know/care
> about the program headers. The program headers describe how the
> segments have to be loaded at runtime. Since some data has moved
> around the program data isn't loaded correctly anymore which causes
> the crash.
>
> To prevent libelf from doing this, and take responsibility of how the
> sections are layed out yourself you have to call:
>
>   elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT);
>
> Before calling elf_update. Note that in that case you are responsible
> for setting/updating the sh_offset fields of the Shdrs yourself.
>
> See for example the elfutils src/elfcompress.c program to see what it
> does in case the Elf file has program headers.
>
> Hope that helps,

Thanks for taking a look! I did not know about this behavior
- this was indeed helpful.

Daniel

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-12-31  5:16 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-28  2:40 Noop round trip through elf_update() causes segfaults Daniel Xu
2023-12-30 17:41 ` Mark Wielaard
2023-12-31  5:16   ` Daniel Xu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).