Re: ld.so: NULL dereference on corrupt library

2021-05-09 Thread Klemens Nanni
On Wed, May 05, 2021 at 02:20:45PM -0900, Philip Guenther wrote:
> IMHO, the benefit of adding this check is almost zero: it gives a slightly
> better experience for a small set of possible data corruption cases, when
> similar corruptions that affect other pages aren't helped at all as it'll
> crash when it executes zeroed text, or accesses zeroed data, or fails to
> find a required symbol because the symbol table was zeroed out.
I agree that it only covers a small subset of all the countless
corruptions and erroneous ld.so might take.

> If we want to protect against that sort of hardware lossage, then a
> filesystem which does so is the way to go, not an alarm on one window of a
> glass house.
And yes, I'd like preventing corruption in the first place as well.

But then again, having such mechanisms around seems very unlikely and a
clean error message telling users *where* corruption took place still
seems worth it;  binutils having a similar check seems to support that.

I sit on the fence here with no strong opinion (also in part because I
barely scratched the surfce of ELF and ld.so so far), so unless someone
else wants such a check/error message in ld.so I'll just drop the diff.



Re: ld.so: NULL dereference on corrupt library

2021-05-05 Thread Philip Guenther
On Tue, May 4, 2021 at 12:43 PM Klemens Nanni  wrote:
...

> I compared my corrupted shared library with an intact copy from ports
> and it showed that the corrupted one was simply zeroed out at some point
> (not truncated) until the end, e.g. readelf(1)'s `-h' or `-l' report
> "Error: no .dynamic section in the dynamic segment".
>
> So this isn't a case of some badly linked library or one that has a few
> bits flipped, it's simply a partial one... seems like bad luck?
>

IMHO, the benefit of adding this check is almost zero: it gives a slightly
better experience for a small set of possible data corruption cases, when
similar corruptions that affect other pages aren't helped at all as it'll
crash when it executes zeroed text, or accesses zeroed data, or fails to
find a required symbol because the symbol table was zeroed out.

If we want to protect against that sort of hardware lossage, then a
filesystem which does so is the way to go, not an alarm on one window of a
glass house.


Philip Guenther


Re: ld.so: NULL dereference on corrupt library

2021-05-05 Thread Martin Pieuchot
On 04/05/21(Tue) 21:41, Klemens Nanni wrote:
> On Thu, Apr 15, 2021 at 03:05:45PM +0200, Mark Kettenis wrote:
> > > > [...] 
> > > > Hence, only access buckets in _dl_find_symbol_obj() if there are any;
> > > > this fixes the crash and in fact allows me to play the song even when
> > > > preloading the currupted library, i.e.
> > > > 
> > > > $ LD_PRELOAD=./libvorbisenc.so.3.1 ogg123 song62.ogg
> > > > 
> > > > now also works with patched ld.so installed -- I'd expected ld.so,
> > > > libvorbis or ogg123 to crash on some other place...
> > > > 
> > > > I'm not sure what to make of this, I also don't know enough about ld.so
> > > > to judge this diff in context, it does however fix an obvious error.
> > > > FWIW, regress/libexec/ld.so runs fine with this diff.
> > > 
> > > I'm not sure if silently ignoring the corruption is the best way to go.
> > 
> > It certainly isn't.  If corruption is detected, the prcess should
> > terminate immedtaley.
> 
> I totally agree, mention of regress passing shouldn't imply that I want
> that diff in, but rather show that it didn't have unexpected drawbacks.
> 
> > > Do you know why `nbuckets' and `buckets_elf' aren't initialized for this
> > > object?  Do you know if _dl_finalize_object() has been call for it?
> 
> Yes, _dl_finalize_object() is always called for it.
> 
> I compared my corrupted shared library with an intact copy from ports
> and it showed that the corrupted one was simply zeroed out at some point
> (not truncated) until the end, e.g. readelf(1)'s `-h' or `-l' report
> "Error: no .dynamic section in the dynamic segment".
> 
> So this isn't a case of some badly linked library or one that has a few
> bits flipped, it's simply a partial one... seems like bad luck?
> 
> > > > Is this a code path that can happen with intact objects?
> > > > Given that the file is obviously corrupted but programs using it still
> > > > (partially) work, should a warning be printed in this case?
> > > 
> > > Indicating that the library is corrupted might indeed be better than
> > > crashing.  However it isn't clear to me where such check should happen.
> 
> I've done just that now as there's nothing else to do.  It is an obscure
> case that I cannot explain without corruption, so very unlikely to
> happen, but now it did...
> 
> > > > Index: resolve.c
> > > > ===
> > > > RCS file: /cvs/src/libexec/ld.so/resolve.c,v
> > > > retrieving revision 1.94
> > > > diff -u -p -r1.94 resolve.c
> > > > --- resolve.c   4 Oct 2019 17:42:16 -   1.94
> > > > +++ resolve.c   14 Apr 2021 15:56:14 -
> > > > @@ -608,7 +608,7 @@ _dl_find_symbol_obj(elf_object_t *obj, s
> > > > return r > 0;
> > > > }
> > > > } while ((*hashval++ & 1U) == 0);
> > > > -   } else {
> > > > +   } else if (obj->nbuckets > 0) {
> > > > Elf_Word si;
> > > >  
> > > > for (si = obj->buckets_elf[sl->sl_elf_hash % 
> > > > obj->nbuckets];
> > > > 
> > > 
> > > 
> 
> readelf(1) detects this corruption as missing (or empty/zeroed out as
> code reading showed);  we could probably to that as well but it'd be
> less trivial and a generalisation of my issue.
> 
> So the new diff simply bails out if there is no symbol hash table, which
> is equally relevant for both ELF and GNU hashes:
> 
>   $ LD_PRELOAD=./bad.so ./ogg123 ~/song62.ogg
>   ld.so: ogg123.test: ./bad.so: no buckets
>   killed
>   $
> 
> Feedback? Objections? OK?

I still don't understand what the corruption is and the check below
doesn't explain that either.  So if I'm developing a library and I see
such message it doesn't give me more info than the previous core dump.

What is corrupted?  The header?  A section is missing?  An offset is
incorrect?  Is there a mismatch between DT_GNU_HASH and DT_HASH?

> Index: resolve.c
> ===
> RCS file: /cvs/src/libexec/ld.so/resolve.c,v
> retrieving revision 1.94
> diff -u -p -r1.94 resolve.c
> --- resolve.c 4 Oct 2019 17:42:16 -   1.94
> +++ resolve.c 29 Apr 2021 22:07:46 -
> @@ -573,6 +573,9 @@ _dl_find_symbol_obj(elf_object_t *obj, s
>  {
>   const Elf_Sym   *symt = obj->dyn.symtab;
>  
> + if (obj->nbuckets == 0)
> + _dl_die("%s: no buckets", obj->load_name);
> +
>   if (obj->status & STAT_GNU_HASH) {
>   uint32_t hash = sl->sl_gnu_hash;
>   Elf_Addr bloom_word;



Re: ld.so: NULL dereference on corrupt library

2021-05-04 Thread Klemens Nanni
On Thu, Apr 15, 2021 at 03:05:45PM +0200, Mark Kettenis wrote:
> > Date: Thu, 15 Apr 2021 14:20:00 +0200
> > From: Martin Pieuchot 
> > Content-Type: text/plain; charset=utf-8
> > Content-Disposition: inline
> > 
> > On 14/04/21(Wed) 18:33, Klemens Nanni wrote:
> > > A bogus libvorbisenc.so.3.1 causes ld.so(1) to crash on my Pinebook Pro
> > > which saw a few NVMe/power related panics:
> > > 
> > >   $ ogg123 song62.ogg
> > >   Segmentation fault (core dumped)
> > > 
> > >   $ egdb -q ogg123 ogg123.core 
> > >   Reading symbols from ogg123...(no debugging symbols found)...done.
> > >   [New process 512916]
> > >   Core was generated by `ogg123'.
> > >   Program terminated with signal SIGSEGV, Segmentation fault.
> > >   #0  0x000d388623e4 in _dl_find_symbol_obj (obj=0xcfae56000, 
> > > sl=0x7dd728) at /usr/src/libexec/ld.so/resolve.c:614
> > >   614 for (si = obj->buckets_elf[sl->sl_elf_hash % 
> > > obj->nbuckets];
> > >   (gdb) p obj->buckets_elf
> > >   There is no member named buckets_elf.
> > > 
> > > (`buckets_elf' is a macro)
> > > 
> > >   (gdb) p obj->hash_u.u_elf.buckets
> > >   $1 = (const Elf_Hash_Word *) 0x0
> > >   (gdb) p obj->nbuckets
> > >   $2 = 0
> > > 
> > > Backtrace for completeness:
> > > 
> > >   (gdb) bt
> > >   #0  0x000d388623e4 in _dl_find_symbol_obj (obj=0xcfae56000, 
> > > sl=0x7dd728) at /usr/src/libexec/ld.so/resolve.c:614
> > >   #1  0x000d38862210 in _dl_find_symbol (name=0xd9e9e6919 
> > > "malloc_options", flags=16, ref_sym=0xd9e9d23f8, req_obj=0xcfae52000) at 
> > > /usr/src/libexec/ld.so/resolve.c:704
> > >   #2  0x000d388603b8 in _dl_md_reloc (object=, 
> > > rel=, relsz=) at 
> > > /usr/src/libexec/ld.so/aarch64/rtld_machine.c:170
> > >   #3  0x000d38864714 in _dl_rtld (object=0xcfae52000) at 
> > > /usr/src/libexec/ld.so/loader.c:722
> > >   #4  0x000d388646dc in _dl_rtld (object=0xcfae52400) at 
> > > /usr/src/libexec/ld.so/loader.c:712
> > >   #5  0x000d388646dc in _dl_rtld (object=0xd6d641400) at 
> > > /usr/src/libexec/ld.so/loader.c:712
> > >   #6  0x000d388646dc in _dl_rtld (object=0xcfae52800) at 
> > > /usr/src/libexec/ld.so/loader.c:712
> > >   #7  0x000d388646dc in _dl_rtld (object=0xcfae53c00) at 
> > > /usr/src/libexec/ld.so/loader.c:712
> > >   #8  0x000d388646dc in _dl_rtld (object=0xcfae56800) at 
> > > /usr/src/libexec/ld.so/loader.c:712
> > >   #9  0x000d388646dc in _dl_rtld (object=0xcfae56400) at 
> > > /usr/src/libexec/ld.so/loader.c:712
> > >   #10 0x000d388646dc in _dl_rtld (object=0xcfae56c00) at 
> > > /usr/src/libexec/ld.so/loader.c:712
> > >   #11 0x000d388646dc in _dl_rtld (object=0xd0b867400) at 
> > > /usr/src/libexec/ld.so/loader.c:712
> > >   #12 0x000d388646dc in _dl_rtld (object=0xd6d63f400) at 
> > > /usr/src/libexec/ld.so/loader.c:712
> > >   #13 0x000d388646dc in _dl_rtld (object=0xcfae53400) at 
> > > /usr/src/libexec/ld.so/loader.c:712
> > >   #14 0x000d388646dc in _dl_rtld (object=0xd6d63f800) at 
> > > /usr/src/libexec/ld.so/loader.c:712
> > >   #15 0x000d388646dc in _dl_rtld (object=0xcfae52c00) at 
> > > /usr/src/libexec/ld.so/loader.c:712
> > >   #16 0x000d388646dc in _dl_rtld (object=0xcfae53000) at 
> > > /usr/src/libexec/ld.so/loader.c:712
> > >   #17 0x000d388646dc in _dl_rtld (object=0xd0b867c00) at 
> > > /usr/src/libexec/ld.so/loader.c:712
> > >   #18 0x000d388646dc in _dl_rtld (object=0xd6d64) at 
> > > /usr/src/libexec/ld.so/loader.c:712
> > >   #19 0x000d388646dc in _dl_rtld (object=0xd6d640c00) at 
> > > /usr/src/libexec/ld.so/loader.c:712
> > >   #20 0x000d388646dc in _dl_rtld (object=0xd0b867000) at 
> > > /usr/src/libexec/ld.so/loader.c:712
> > >   #21 0x000d388646dc in _dl_rtld (object=0xcfae56000) at 
> > > /usr/src/libexec/ld.so/loader.c:712
> > >   #22 0x000d388646dc in _dl_rtld (object=0xd0b867800) at 
> > > /usr/src/libexec/ld.so/loader.c:712
> > >   #23 0x000d3886b618 in _dl_boot (argv=, 
> > > envp=, dyn_loff=56782815232, dl_data=0x7ddde4) at 
> > > /usr/src/libexec/ld.so/loader.c:663
> > >   #24 0x000d3886a044 in _dl_start () at 
> > > /usr/src/libexec/ld.so/aarch64/ldasm.S:59
> > >   Backtrace stopped: previous frame identical to this frame (corrupt 
> > > stack?)
> > > 
> > > 
> > > libvorbis being the culprit wasn't clear at all, but I went through
> > > pkg_check(1) to see checksum mismatches in the "libvorbis" package.
> > > 
> > > tl;dr: I Upgraded to the latest snapshot, saved the currupted libraries,
> > > deinstalled all packages with `pkg_delete -X', installed "vorbis-tools"
> > > for ogg123(1) (pulling in "libvorbis") and the song played fine using
> > > valid files.
> > > 
> > > Forcing the corrupted library I can reproduce, though:
> > > 
> > >   $ LD_PRELOAD=./libvorbisenc.so.3.1 ogg123 song62.ogg
> > >   Segmentation fault (core dumped)
> > > 
> > > So that's really this shared object and not any other currupted files.
> > > 

Re: ld.so: NULL dereference on corrupt library

2021-04-15 Thread Mark Kettenis
> Date: Thu, 15 Apr 2021 14:20:00 +0200
> From: Martin Pieuchot 
> Content-Type: text/plain; charset=utf-8
> Content-Disposition: inline
> 
> On 14/04/21(Wed) 18:33, Klemens Nanni wrote:
> > A bogus libvorbisenc.so.3.1 causes ld.so(1) to crash on my Pinebook Pro
> > which saw a few NVMe/power related panics:
> > 
> > $ ogg123 song62.ogg
> > Segmentation fault (core dumped)
> > 
> > $ egdb -q ogg123 ogg123.core 
> > Reading symbols from ogg123...(no debugging symbols found)...done.
> > [New process 512916]
> > Core was generated by `ogg123'.
> > Program terminated with signal SIGSEGV, Segmentation fault.
> > #0  0x000d388623e4 in _dl_find_symbol_obj (obj=0xcfae56000, 
> > sl=0x7dd728) at /usr/src/libexec/ld.so/resolve.c:614
> > 614 for (si = obj->buckets_elf[sl->sl_elf_hash % 
> > obj->nbuckets];
> > (gdb) p obj->buckets_elf
> > There is no member named buckets_elf.
> > 
> > (`buckets_elf' is a macro)
> > 
> > (gdb) p obj->hash_u.u_elf.buckets
> > $1 = (const Elf_Hash_Word *) 0x0
> > (gdb) p obj->nbuckets
> > $2 = 0
> > 
> > Backtrace for completeness:
> > 
> > (gdb) bt
> > #0  0x000d388623e4 in _dl_find_symbol_obj (obj=0xcfae56000, 
> > sl=0x7dd728) at /usr/src/libexec/ld.so/resolve.c:614
> > #1  0x000d38862210 in _dl_find_symbol (name=0xd9e9e6919 
> > "malloc_options", flags=16, ref_sym=0xd9e9d23f8, req_obj=0xcfae52000) at 
> > /usr/src/libexec/ld.so/resolve.c:704
> > #2  0x000d388603b8 in _dl_md_reloc (object=, 
> > rel=, relsz=) at 
> > /usr/src/libexec/ld.so/aarch64/rtld_machine.c:170
> > #3  0x000d38864714 in _dl_rtld (object=0xcfae52000) at 
> > /usr/src/libexec/ld.so/loader.c:722
> > #4  0x000d388646dc in _dl_rtld (object=0xcfae52400) at 
> > /usr/src/libexec/ld.so/loader.c:712
> > #5  0x000d388646dc in _dl_rtld (object=0xd6d641400) at 
> > /usr/src/libexec/ld.so/loader.c:712
> > #6  0x000d388646dc in _dl_rtld (object=0xcfae52800) at 
> > /usr/src/libexec/ld.so/loader.c:712
> > #7  0x000d388646dc in _dl_rtld (object=0xcfae53c00) at 
> > /usr/src/libexec/ld.so/loader.c:712
> > #8  0x000d388646dc in _dl_rtld (object=0xcfae56800) at 
> > /usr/src/libexec/ld.so/loader.c:712
> > #9  0x000d388646dc in _dl_rtld (object=0xcfae56400) at 
> > /usr/src/libexec/ld.so/loader.c:712
> > #10 0x000d388646dc in _dl_rtld (object=0xcfae56c00) at 
> > /usr/src/libexec/ld.so/loader.c:712
> > #11 0x000d388646dc in _dl_rtld (object=0xd0b867400) at 
> > /usr/src/libexec/ld.so/loader.c:712
> > #12 0x000d388646dc in _dl_rtld (object=0xd6d63f400) at 
> > /usr/src/libexec/ld.so/loader.c:712
> > #13 0x000d388646dc in _dl_rtld (object=0xcfae53400) at 
> > /usr/src/libexec/ld.so/loader.c:712
> > #14 0x000d388646dc in _dl_rtld (object=0xd6d63f800) at 
> > /usr/src/libexec/ld.so/loader.c:712
> > #15 0x000d388646dc in _dl_rtld (object=0xcfae52c00) at 
> > /usr/src/libexec/ld.so/loader.c:712
> > #16 0x000d388646dc in _dl_rtld (object=0xcfae53000) at 
> > /usr/src/libexec/ld.so/loader.c:712
> > #17 0x000d388646dc in _dl_rtld (object=0xd0b867c00) at 
> > /usr/src/libexec/ld.so/loader.c:712
> > #18 0x000d388646dc in _dl_rtld (object=0xd6d64) at 
> > /usr/src/libexec/ld.so/loader.c:712
> > #19 0x000d388646dc in _dl_rtld (object=0xd6d640c00) at 
> > /usr/src/libexec/ld.so/loader.c:712
> > #20 0x000d388646dc in _dl_rtld (object=0xd0b867000) at 
> > /usr/src/libexec/ld.so/loader.c:712
> > #21 0x000d388646dc in _dl_rtld (object=0xcfae56000) at 
> > /usr/src/libexec/ld.so/loader.c:712
> > #22 0x000d388646dc in _dl_rtld (object=0xd0b867800) at 
> > /usr/src/libexec/ld.so/loader.c:712
> > #23 0x000d3886b618 in _dl_boot (argv=, 
> > envp=, dyn_loff=56782815232, dl_data=0x7ddde4) at 
> > /usr/src/libexec/ld.so/loader.c:663
> > #24 0x000d3886a044 in _dl_start () at 
> > /usr/src/libexec/ld.so/aarch64/ldasm.S:59
> > Backtrace stopped: previous frame identical to this frame (corrupt 
> > stack?)
> > 
> > 
> > libvorbis being the culprit wasn't clear at all, but I went through
> > pkg_check(1) to see checksum mismatches in the "libvorbis" package.
> > 
> > tl;dr: I Upgraded to the latest snapshot, saved the currupted libraries,
> > deinstalled all packages with `pkg_delete -X', installed "vorbis-tools"
> > for ogg123(1) (pulling in "libvorbis") and the song played fine using
> > valid files.
> > 
> > Forcing the corrupted library I can reproduce, though:
> > 
> > $ LD_PRELOAD=./libvorbisenc.so.3.1 ogg123 song62.ogg
> > Segmentation fault (core dumped)
> > 
> > So that's really this shared object and not any other currupted files.
> > 
> > I'm not familiar with ld.so internals but the NULL dereference seems
> > easy to avoid based on the condition that is used to set the `buckets'
> > member in resolve.c:408f:
> > 
> >

Re: ld.so: NULL dereference on corrupt library

2021-04-15 Thread Martin Pieuchot
On 14/04/21(Wed) 18:33, Klemens Nanni wrote:
> A bogus libvorbisenc.so.3.1 causes ld.so(1) to crash on my Pinebook Pro
> which saw a few NVMe/power related panics:
> 
>   $ ogg123 song62.ogg
>   Segmentation fault (core dumped)
> 
>   $ egdb -q ogg123 ogg123.core 
>   Reading symbols from ogg123...(no debugging symbols found)...done.
>   [New process 512916]
>   Core was generated by `ogg123'.
>   Program terminated with signal SIGSEGV, Segmentation fault.
>   #0  0x000d388623e4 in _dl_find_symbol_obj (obj=0xcfae56000, 
> sl=0x7dd728) at /usr/src/libexec/ld.so/resolve.c:614
>   614 for (si = obj->buckets_elf[sl->sl_elf_hash % 
> obj->nbuckets];
>   (gdb) p obj->buckets_elf
>   There is no member named buckets_elf.
> 
> (`buckets_elf' is a macro)
> 
>   (gdb) p obj->hash_u.u_elf.buckets
>   $1 = (const Elf_Hash_Word *) 0x0
>   (gdb) p obj->nbuckets
>   $2 = 0
> 
> Backtrace for completeness:
> 
>   (gdb) bt
>   #0  0x000d388623e4 in _dl_find_symbol_obj (obj=0xcfae56000, 
> sl=0x7dd728) at /usr/src/libexec/ld.so/resolve.c:614
>   #1  0x000d38862210 in _dl_find_symbol (name=0xd9e9e6919 
> "malloc_options", flags=16, ref_sym=0xd9e9d23f8, req_obj=0xcfae52000) at 
> /usr/src/libexec/ld.so/resolve.c:704
>   #2  0x000d388603b8 in _dl_md_reloc (object=, 
> rel=, relsz=) at 
> /usr/src/libexec/ld.so/aarch64/rtld_machine.c:170
>   #3  0x000d38864714 in _dl_rtld (object=0xcfae52000) at 
> /usr/src/libexec/ld.so/loader.c:722
>   #4  0x000d388646dc in _dl_rtld (object=0xcfae52400) at 
> /usr/src/libexec/ld.so/loader.c:712
>   #5  0x000d388646dc in _dl_rtld (object=0xd6d641400) at 
> /usr/src/libexec/ld.so/loader.c:712
>   #6  0x000d388646dc in _dl_rtld (object=0xcfae52800) at 
> /usr/src/libexec/ld.so/loader.c:712
>   #7  0x000d388646dc in _dl_rtld (object=0xcfae53c00) at 
> /usr/src/libexec/ld.so/loader.c:712
>   #8  0x000d388646dc in _dl_rtld (object=0xcfae56800) at 
> /usr/src/libexec/ld.so/loader.c:712
>   #9  0x000d388646dc in _dl_rtld (object=0xcfae56400) at 
> /usr/src/libexec/ld.so/loader.c:712
>   #10 0x000d388646dc in _dl_rtld (object=0xcfae56c00) at 
> /usr/src/libexec/ld.so/loader.c:712
>   #11 0x000d388646dc in _dl_rtld (object=0xd0b867400) at 
> /usr/src/libexec/ld.so/loader.c:712
>   #12 0x000d388646dc in _dl_rtld (object=0xd6d63f400) at 
> /usr/src/libexec/ld.so/loader.c:712
>   #13 0x000d388646dc in _dl_rtld (object=0xcfae53400) at 
> /usr/src/libexec/ld.so/loader.c:712
>   #14 0x000d388646dc in _dl_rtld (object=0xd6d63f800) at 
> /usr/src/libexec/ld.so/loader.c:712
>   #15 0x000d388646dc in _dl_rtld (object=0xcfae52c00) at 
> /usr/src/libexec/ld.so/loader.c:712
>   #16 0x000d388646dc in _dl_rtld (object=0xcfae53000) at 
> /usr/src/libexec/ld.so/loader.c:712
>   #17 0x000d388646dc in _dl_rtld (object=0xd0b867c00) at 
> /usr/src/libexec/ld.so/loader.c:712
>   #18 0x000d388646dc in _dl_rtld (object=0xd6d64) at 
> /usr/src/libexec/ld.so/loader.c:712
>   #19 0x000d388646dc in _dl_rtld (object=0xd6d640c00) at 
> /usr/src/libexec/ld.so/loader.c:712
>   #20 0x000d388646dc in _dl_rtld (object=0xd0b867000) at 
> /usr/src/libexec/ld.so/loader.c:712
>   #21 0x000d388646dc in _dl_rtld (object=0xcfae56000) at 
> /usr/src/libexec/ld.so/loader.c:712
>   #22 0x000d388646dc in _dl_rtld (object=0xd0b867800) at 
> /usr/src/libexec/ld.so/loader.c:712
>   #23 0x000d3886b618 in _dl_boot (argv=, 
> envp=, dyn_loff=56782815232, dl_data=0x7ddde4) at 
> /usr/src/libexec/ld.so/loader.c:663
>   #24 0x000d3886a044 in _dl_start () at 
> /usr/src/libexec/ld.so/aarch64/ldasm.S:59
>   Backtrace stopped: previous frame identical to this frame (corrupt 
> stack?)
> 
> 
> libvorbis being the culprit wasn't clear at all, but I went through
> pkg_check(1) to see checksum mismatches in the "libvorbis" package.
> 
> tl;dr: I Upgraded to the latest snapshot, saved the currupted libraries,
> deinstalled all packages with `pkg_delete -X', installed "vorbis-tools"
> for ogg123(1) (pulling in "libvorbis") and the song played fine using
> valid files.
> 
> Forcing the corrupted library I can reproduce, though:
> 
>   $ LD_PRELOAD=./libvorbisenc.so.3.1 ogg123 song62.ogg
>   Segmentation fault (core dumped)
> 
> So that's really this shared object and not any other currupted files.
> 
> I'm not familiar with ld.so internals but the NULL dereference seems
> easy to avoid based on the condition that is used to set the `buckets'
> member in resolve.c:408f:
> 
>   if (object->Dyn.info[DT_HASH] != 0) {
>   Elf_Hash_Word *hashtab =
>   (Elf_Hash_Word *)(object->Dyn.info[DT_HASH] + obase);
> 
>   object->nchains = hashtab[1];
>   if (object->nbuckets == 0) {
> 

ld.so: NULL dereference on corrupt library

2021-04-14 Thread Klemens Nanni
A bogus libvorbisenc.so.3.1 causes ld.so(1) to crash on my Pinebook Pro
which saw a few NVMe/power related panics:

$ ogg123 song62.ogg
Segmentation fault (core dumped)

$ egdb -q ogg123 ogg123.core 
Reading symbols from ogg123...(no debugging symbols found)...done.
[New process 512916]
Core was generated by `ogg123'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x000d388623e4 in _dl_find_symbol_obj (obj=0xcfae56000, 
sl=0x7dd728) at /usr/src/libexec/ld.so/resolve.c:614
614 for (si = obj->buckets_elf[sl->sl_elf_hash % 
obj->nbuckets];
(gdb) p obj->buckets_elf
There is no member named buckets_elf.

(`buckets_elf' is a macro)

(gdb) p obj->hash_u.u_elf.buckets
$1 = (const Elf_Hash_Word *) 0x0
(gdb) p obj->nbuckets
$2 = 0

Backtrace for completeness:

(gdb) bt
#0  0x000d388623e4 in _dl_find_symbol_obj (obj=0xcfae56000, 
sl=0x7dd728) at /usr/src/libexec/ld.so/resolve.c:614
#1  0x000d38862210 in _dl_find_symbol (name=0xd9e9e6919 
"malloc_options", flags=16, ref_sym=0xd9e9d23f8, req_obj=0xcfae52000) at 
/usr/src/libexec/ld.so/resolve.c:704
#2  0x000d388603b8 in _dl_md_reloc (object=, 
rel=, relsz=) at 
/usr/src/libexec/ld.so/aarch64/rtld_machine.c:170
#3  0x000d38864714 in _dl_rtld (object=0xcfae52000) at 
/usr/src/libexec/ld.so/loader.c:722
#4  0x000d388646dc in _dl_rtld (object=0xcfae52400) at 
/usr/src/libexec/ld.so/loader.c:712
#5  0x000d388646dc in _dl_rtld (object=0xd6d641400) at 
/usr/src/libexec/ld.so/loader.c:712
#6  0x000d388646dc in _dl_rtld (object=0xcfae52800) at 
/usr/src/libexec/ld.so/loader.c:712
#7  0x000d388646dc in _dl_rtld (object=0xcfae53c00) at 
/usr/src/libexec/ld.so/loader.c:712
#8  0x000d388646dc in _dl_rtld (object=0xcfae56800) at 
/usr/src/libexec/ld.so/loader.c:712
#9  0x000d388646dc in _dl_rtld (object=0xcfae56400) at 
/usr/src/libexec/ld.so/loader.c:712
#10 0x000d388646dc in _dl_rtld (object=0xcfae56c00) at 
/usr/src/libexec/ld.so/loader.c:712
#11 0x000d388646dc in _dl_rtld (object=0xd0b867400) at 
/usr/src/libexec/ld.so/loader.c:712
#12 0x000d388646dc in _dl_rtld (object=0xd6d63f400) at 
/usr/src/libexec/ld.so/loader.c:712
#13 0x000d388646dc in _dl_rtld (object=0xcfae53400) at 
/usr/src/libexec/ld.so/loader.c:712
#14 0x000d388646dc in _dl_rtld (object=0xd6d63f800) at 
/usr/src/libexec/ld.so/loader.c:712
#15 0x000d388646dc in _dl_rtld (object=0xcfae52c00) at 
/usr/src/libexec/ld.so/loader.c:712
#16 0x000d388646dc in _dl_rtld (object=0xcfae53000) at 
/usr/src/libexec/ld.so/loader.c:712
#17 0x000d388646dc in _dl_rtld (object=0xd0b867c00) at 
/usr/src/libexec/ld.so/loader.c:712
#18 0x000d388646dc in _dl_rtld (object=0xd6d64) at 
/usr/src/libexec/ld.so/loader.c:712
#19 0x000d388646dc in _dl_rtld (object=0xd6d640c00) at 
/usr/src/libexec/ld.so/loader.c:712
#20 0x000d388646dc in _dl_rtld (object=0xd0b867000) at 
/usr/src/libexec/ld.so/loader.c:712
#21 0x000d388646dc in _dl_rtld (object=0xcfae56000) at 
/usr/src/libexec/ld.so/loader.c:712
#22 0x000d388646dc in _dl_rtld (object=0xd0b867800) at 
/usr/src/libexec/ld.so/loader.c:712
#23 0x000d3886b618 in _dl_boot (argv=, 
envp=, dyn_loff=56782815232, dl_data=0x7ddde4) at 
/usr/src/libexec/ld.so/loader.c:663
#24 0x000d3886a044 in _dl_start () at 
/usr/src/libexec/ld.so/aarch64/ldasm.S:59
Backtrace stopped: previous frame identical to this frame (corrupt 
stack?)


libvorbis being the culprit wasn't clear at all, but I went through
pkg_check(1) to see checksum mismatches in the "libvorbis" package.

tl;dr: I Upgraded to the latest snapshot, saved the currupted libraries,
deinstalled all packages with `pkg_delete -X', installed "vorbis-tools"
for ogg123(1) (pulling in "libvorbis") and the song played fine using
valid files.

Forcing the corrupted library I can reproduce, though:

$ LD_PRELOAD=./libvorbisenc.so.3.1 ogg123 song62.ogg
Segmentation fault (core dumped)

So that's really this shared object and not any other currupted files.

I'm not familiar with ld.so internals but the NULL dereference seems
easy to avoid based on the condition that is used to set the `buckets'
member in resolve.c:408f:

if (object->Dyn.info[DT_HASH] != 0) {
Elf_Hash_Word *hashtab =
(Elf_Hash_Word *)(object->Dyn.info[DT_HASH] + obase);

object->nchains = hashtab[1];
if (object->nbuckets == 0) {
object->nbuckets = hashtab[0];
object->buckets_elf = hashtab + 2;
object->chains_elf = object->buckets_el