[PATCH] libelf/elf_end.c: check data_list.data.d.d_buf before free it

Mark Wielaard mark@klomp.org
Fri Aug 17 10:11:00 GMT 2018


Hi Robert,

[I don't have very good internet connectivity so cannot easily get all
 the bits and sources to replicate/inspect. So apologies if I am
 misinterpreting something.]

On Fri, Aug 17, 2018 at 04:25:07PM +0800, Robert Yang wrote:
> On 08/17/2018 03:25 AM, Mark Wielaard wrote:
> > On Thu, Aug 16, 2018 at 10:34:23AM +0800, Robert Yang wrote:
> > > The one which actually saves the data is data_list.data.d.d_buf, so check it
> > > before free rawdata_base.
> > > 
> > > This can fix a segmentation fault when prelink libqb_1.0.3:
> > > prelink: /usr/lib/libqb.so.0.18.2: Symbol section index outside of section numbers
> > > 
> > > The segmentation fault happens when prelink call elf_end().
> > 
> > Could you run your reproducer under valgrind and show what it
> > says before your patch? And/Or post the file (libqb) to replicate
> > the reproducer somewhere to see exactly what goes wrong?
> > 
> > I don't fully understand what is going wrong. Is the section data
> > pointing to the file data or something created by elf_newdata?
> 
> Thanks for the reply, I found this problem in a cross build environment,
> but we are using elfutils as native tool (directly running on host), its
> version is 0.172, srcrev=01e87ab4c5a6a249c04e22a97a4221d3.
> 
> $ VALGRIND_LIB=/path/to/usr/lib/valgrind valgrind prelink --root
> /path/to/core-image-minimal/1.0-r0/rootfs -amR -N -c /etc/prelink.conf
> --dynamic-linker /lib/ld-linux-x86-64.so.2 -v
> 
> Here are the problems related to elfutils:
> 
> prelink: /usr/lib/libqb.so.0.19.0: Symbol section index outside of section numbers
> ==25330== Invalid free() / delete / delete[] / realloc()
> ==25330==    at 0x4C3026B: free (in /path/to/recipe-sysroot-native/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
> ==25330==    by 0x50991F5: elf_end (elf_end.c:171)
> ==25330==    by 0x41E916: ??? (in /path/to/recipe-sysroot-native/usr/sbin/prelink)
> ==25330==    by 0x422233: ??? (in /path/to/recipe-sysroot-native/usr/sbin/prelink)
> ==25330==    by 0x408BE1: ??? (in /path/to/recipe-sysroot-native/usr/sbin/prelink)
> ==25330==    by 0x409015: ??? (in /path/to/recipe-sysroot-native/usr/sbin/prelink)
> ==25330==    by 0x4038FB: ??? (in /path/to/recipe-sysroot-native/usr/sbin/prelink)
> ==25330==    by 0x52CF04A: (below main) (in /buildarea1/lyang1/test_up/tmp/sysroots-uninative/x86_64-linux/lib/libc-2.27.so)
> ==25330==  Address 0x9305300 is 0 bytes inside a block of size 20 free'd
> ==25330==    at 0x4C3026B: free (in /path/to/recipe-sysroot-native/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
> ==25330==    by 0x41E8B7: ??? (in /path/to/recipe-sysroot-native/usr/sbin/prelink)
> ==25330==    by 0x422233: ??? (in /path/to/recipe-sysroot-native/usr/sbin/prelink)
> ==25330==    by 0x408BE1: ??? (in /path/to/recipe-sysroot-native/usr/sbin/prelink)
> ==25330==    by 0x409015: ??? (in /path/to/recipe-sysroot-native/usr/sbin/prelink)
> ==25330==    by 0x4038FB: ??? (in /path/to/recipe-sysroot-native/usr/sbin/prelink)
> ==25330==    by 0x52CF04A: (below main) (in /buildarea1/lyang1/test_up/tmp/sysroots-uninative/x86_64-linux/lib/libc-2.27.so)
> ==25330==  Block was alloc'd at
> ==25330==    at 0x4C2F03F: malloc (in /path/to/recipe-sysroot-native/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
> ==25330==    by 0x509DE8E: __libelf_set_rawdata_wrlock (elf_getdata.c:329)
> ==25330==    by 0x509E20E: __elf_getdata_rdlock (elf_getdata.c:532)
> ==25330==    by 0x509E24D: elf_getdata (elf_getdata.c:559)
> ==25330==    by 0x420A70: ??? (in /path/to/recipe-sysroot-native/usr/sbin/prelink)
> ==25330==    by 0x413860: ??? (in /path/to/recipe-sysroot-native/usr/sbin/prelink)
> ==25330==    by 0x408D64: ??? (in /path/to/recipe-sysroot-native/usr/sbin/prelink)
> ==25330==    by 0x409015: ??? (in /path/to/recipe-sysroot-native/usr/sbin/prelink)
> ==25330==    by 0x4038FB: ??? (in /path/to/recipe-sysroot-native/usr/sbin/prelink)
> ==25330==    by 0x52CF04A: (below main) (in /buildarea1/lyang1/test_up/tmp/sysroots-uninative/x86_64-linux/lib/libc-2.27.so)

Thanks, that does suggest to me there is a bug in prelink.
Although it isn't completely clear. If you could run the same with
prelink debuginfo so we can see the source lines that would be great.

The reason I think this is a prelink issues is because it looks like
it is calling elf_getdata () to get the data, and then frees the buffer.
The idea is that you only own the data of an elf section if you created
it yourself with elf_newdata (). Otherwise, as seems to have happened
here, libelf owns the data buffer and has to free it.

I think that prelink is preparing the ELF file, but then half way
through encounters an error. It then frees all the ELF section data it
believed it created itself. But because of the error it probably didn't
(yet) do that. And so frees some data that it got directly from
elf_getdata () and didn't create itself. Then it calls elf_end () and
libelf also thinks it owns that data and frees it again.

It probably only happens when prelink encounters some other issue while
processing a file.

Cheers,

Mark



More information about the Elfutils-devel mailing list