[PATCH] libelf/elf_end.c: check data_list.data.d.d_buf before free it
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(). Signed-off-by: Robert Yang --- libelf/elf_end.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libelf/elf_end.c b/libelf/elf_end.c index 160f0b8..5388e80 100644 --- a/libelf/elf_end.c +++ b/libelf/elf_end.c @@ -165,9 +165,10 @@ elf_end (Elf *elf) /* The section data is allocated if we couldn't mmap the file. Or if we had to decompress. */ - if (elf->map_address == NULL + if ((elf->map_address == NULL || scn->rawdata_base == scn->zdata_base || (scn->flags & ELF_F_MALLOCED) != 0) + && (scn->data_list.data.d.d_buf != NULL)) free (scn->rawdata_base); /* Free the list of data buffers for the section. -- 2.7.4
Re: [PATCH] libelf/elf_end.c: check data_list.data.d.d_buf before free it
On 08/17/2018 03:25 AM, Mark Wielaard wrote: Hi, 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) // Robert Thanks, Mark
Re: [PATCH] libelf/elf_end.c: check data_list.data.d.d_buf before free it
On 08/17/2018 06:10 PM, Mark Wielaard wrote: 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 issu
[PATCH V1] libelf/elf_end.c: check data_list.data.d.d_buf before free it
* V2 - Also check data_list.data.d.d_buf before free scn->data_base, this can fix prelink error libqb_1.0.3 on mips and mips64. * V1 - Initial version Robert Yang (1): libelf/elf_end.c: check data_list.data.d.d_buf before free it libelf/elf_end.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) -- 2.7.4
[PATCH V2] libelf/elf_end.c: check data_list.data.d.d_buf before free it
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(). Signed-off-by: Robert Yang --- libelf/elf_end.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libelf/elf_end.c b/libelf/elf_end.c index 160f0b8..5280a70 100644 --- a/libelf/elf_end.c +++ b/libelf/elf_end.c @@ -160,14 +160,16 @@ elf_end (Elf *elf) architecture doesn't require overly stringent alignment the raw data buffer is the same as the one used for presenting to the caller. */ - if (scn->data_base != scn->rawdata_base) + if ((scn->data_base != scn->rawdata_base) + && (scn->data_list.data.d.d_buf != NULL)) free (scn->data_base); /* The section data is allocated if we couldn't mmap the file. Or if we had to decompress. */ - if (elf->map_address == NULL + if ((elf->map_address == NULL || scn->rawdata_base == scn->zdata_base || (scn->flags & ELF_F_MALLOCED) != 0) + && (scn->data_list.data.d.d_buf != NULL)) free (scn->rawdata_base); /* Free the list of data buffers for the section. -- 2.7.4
Re: [PATCH V2] libelf/elf_end.c: check data_list.data.d.d_buf before free it
On 08/31/2018 03:57 AM, Mark Wielaard wrote: On Wed, Aug 29, 2018 at 04:53:20PM +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(). Are you sure this isn't a bug in prelink like we discussed last time? If it isn't, can you give a short example how this issue happens? Sorry, I can't make sure which ones is wrong, libqb, prelink or elfutils, this happens when cross compiling, and I've built more than 4 hunderds of packages, libqb 1.0.3 is the only package which has the problem, I've also fixed prelink, but it is another segmentation fault error. I've reported this problem to libqb community, then they make another branch for libqb, and it works well without any errors, the branch is topic-no-ldsection, and the commit is: https://github.com/ClusterLabs/libqb/commit/358e0120d8cd288095907869d3f8da92937188a0 I've used gdb/valgrind to debug this segfault, but can't find prelink's distinct problem, the only problem I found is that elfutil's elf_end() free() a NULL memory, so I made this patch. I think that someone who uses libqb_1.0.3 + elfutils + prelink + crosscompile would meet the same problem. // Robert Thanks, Mark
Re: [PATCH V2] libelf/elf_end.c: check data_list.data.d.d_buf before free it
On 08/31/2018 05:35 PM, Mark Wielaard wrote: Hi Robert, On Fri, 2018-08-31 at 10:17 +0800, Robert Yang wrote: Sorry, I can't make sure which ones is wrong, libqb, prelink or elfutils, this happens when cross compiling, and I've built more than 4 hunderds of packages, libqb 1.0.3 is the only package which has the problem, I've also fixed prelink, but it is another segmentation fault error. I've reported this problem to libqb community, then they make another branch for libqb, and it works well without any errors, the branch is topic-no-ldsection, and the commit is: https://github.com/ClusterLabs/libqb/commit/358e0120d8cd288095907869d3f8da92937188a0 So, this is a separate issue? Or does the prelink problem also go away when using that commit/branch? I've used gdb/valgrind to debug this segfault, but can't find prelink's distinct problem, the only problem I found is that elfutil's elf_end() free() a NULL memory, so I made this patch. OK. So I believe that is because prelink's error handling seems wrong. It seems to assume it adding the ELF data buffer itself, so frees it, but the data actually seemed to come from elf_getdata, so shouldn't have been freed by prelink. Thanks, I will investigate that. // Robert Thanks, Mark