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 0x0000000d388623e4 in _dl_find_symbol_obj (obj=0xcfae56000, > sl=0x7ffffdd728) 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 0x0000000d388623e4 in _dl_find_symbol_obj (obj=0xcfae56000, > sl=0x7ffffdd728) at /usr/src/libexec/ld.so/resolve.c:614 > #1 0x0000000d38862210 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 0x0000000d388603b8 in _dl_md_reloc (object=<optimized out>, > rel=<optimized out>, relsz=<optimized out>) at > /usr/src/libexec/ld.so/aarch64/rtld_machine.c:170 > #3 0x0000000d38864714 in _dl_rtld (object=0xcfae52000) at > /usr/src/libexec/ld.so/loader.c:722 > #4 0x0000000d388646dc in _dl_rtld (object=0xcfae52400) at > /usr/src/libexec/ld.so/loader.c:712 > #5 0x0000000d388646dc in _dl_rtld (object=0xd6d641400) at > /usr/src/libexec/ld.so/loader.c:712 > #6 0x0000000d388646dc in _dl_rtld (object=0xcfae52800) at > /usr/src/libexec/ld.so/loader.c:712 > #7 0x0000000d388646dc in _dl_rtld (object=0xcfae53c00) at > /usr/src/libexec/ld.so/loader.c:712 > #8 0x0000000d388646dc in _dl_rtld (object=0xcfae56800) at > /usr/src/libexec/ld.so/loader.c:712 > #9 0x0000000d388646dc in _dl_rtld (object=0xcfae56400) at > /usr/src/libexec/ld.so/loader.c:712 > #10 0x0000000d388646dc in _dl_rtld (object=0xcfae56c00) at > /usr/src/libexec/ld.so/loader.c:712 > #11 0x0000000d388646dc in _dl_rtld (object=0xd0b867400) at > /usr/src/libexec/ld.so/loader.c:712 > #12 0x0000000d388646dc in _dl_rtld (object=0xd6d63f400) at > /usr/src/libexec/ld.so/loader.c:712 > #13 0x0000000d388646dc in _dl_rtld (object=0xcfae53400) at > /usr/src/libexec/ld.so/loader.c:712 > #14 0x0000000d388646dc in _dl_rtld (object=0xd6d63f800) at > /usr/src/libexec/ld.so/loader.c:712 > #15 0x0000000d388646dc in _dl_rtld (object=0xcfae52c00) at > /usr/src/libexec/ld.so/loader.c:712 > #16 0x0000000d388646dc in _dl_rtld (object=0xcfae53000) at > /usr/src/libexec/ld.so/loader.c:712 > #17 0x0000000d388646dc in _dl_rtld (object=0xd0b867c00) at > /usr/src/libexec/ld.so/loader.c:712 > #18 0x0000000d388646dc in _dl_rtld (object=0xd6d640000) at > /usr/src/libexec/ld.so/loader.c:712 > #19 0x0000000d388646dc in _dl_rtld (object=0xd6d640c00) at > /usr/src/libexec/ld.so/loader.c:712 > #20 0x0000000d388646dc in _dl_rtld (object=0xd0b867000) at > /usr/src/libexec/ld.so/loader.c:712 > #21 0x0000000d388646dc in _dl_rtld (object=0xcfae56000) at > /usr/src/libexec/ld.so/loader.c:712 > #22 0x0000000d388646dc in _dl_rtld (object=0xd0b867800) at > /usr/src/libexec/ld.so/loader.c:712 > #23 0x0000000d3886b618 in _dl_boot (argv=<optimized out>, > envp=<optimized out>, dyn_loff=56782815232, dl_data=0x7ffffddde4) at > /usr/src/libexec/ld.so/loader.c:663 > #24 0x0000000d3886a044 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_elf + > object->nbuckets; > } > } > > 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. 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? > 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. > Feedback? > > PS: I can upload/mail the corrupted library if someone wants to poke it. > > 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 -0000 1.94 > +++ resolve.c 14 Apr 2021 15:56:14 -0000 > @@ -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]; >