Hi,
I was trying to compile a buildroot-2019.02.4 system for an aarch64
platform using gcc 8.3.0 and uClibc-ng-1.0.31. Everything seemed to boot
fine, but when I added the ntpd daemon, the daemon kept segfaulting.
Some debugging showed, that the segfault happened inside the res_init
function, so i made the following test program:
----test_res_init.c----
#include <resolv.h>
void main(void)
{
res_init();
}
-----------------------
This program always segfaults as soon as res_init tries to access the
_res structure. Some more debugging revealed, that there seems to be a
general problem with accessing thread local storage from a dynamicly
linked library, so I wrote the following test code:
----test_lib.c----
#include <stdio.h>
int ii;
__thread int *iip = ⅈ
void print_ptrs(void)
{
printf("print_ptrs:\n");
printf("&iip = %p\n", &iip);
printf("&ii = %p\n", &ii);
printf("iip = %p\n", iip);
}
----test_tls.c----
#include <stdio.h>
void print_ptrs(void);
extern int ii;
extern __thread int *iip;
void main(void)
{
printf("main:\n");
printf("&iip = %p\n", &iip);
printf("&ii = %p\n", &ii);
printf("iip = %p\n", iip);
print_ptrs();
}
------------------
When compiling the source linke this:
# aarch64-linux-gcc -g -fPIC -c -o test_lib.o test_lib.c
# aarch64-linux-gcc -shared -o test_lib.so test_lib.o
# aarch64-linux-gcc -g test_tls.c test_lib.so -o test_tls
the result looks like this:
-------------------------------
# LD_LIBRARY_PATH=/root /root/test_tls
main:
&iip = 0x7fa0d756d0
&ii = 0x411048
iip = 0x411048
print_ptrs:
&iip = 0xff41ac4d90
&ii = 0x411048
[ 7654.009770] test_tls[1942]: unhandled level 0 translation fault (11)
at 0xff41ac4d90, esr 0x92000004
[ 7654.018844] pgd = ffffffc07d48c000
[ 7654.027775] [ff41ac4d90] *pgd=0000000000000000
[ 7654.036007] , *pud=0000000000000000
[ 7654.039488]
[ 7654.040951]
[ 7654.042441] CPU: 2 PID: 1942 Comm: test_tls Not tainted
4.9.0-g196f33d0-dirty #6
[ 7654.049820] Hardware name: xlnx,zynqmp (DT)
[ 7654.053981] task: ffffffc05e71ad00 task.stack: ffffffc05d9d4000
[ 7654.059884] PC is at 0x7fa0d4f8f4
[ 7654.063186] LR is at 0x7fa0d4f8ec
[ 7654.066478] pc : [<0000007fa0d4f8f4>] lr : [<0000007fa0d4f8ec>]
pstate: 60000000
[ 7654.073864] sp : 0000007fe5405170
[ 7654.077148] x29: 0000007fe5405170 x28: 0000000000000000
[ 7654.082442] x27: 0000000000000000 x26: 0000000000000000
[ 7654.087736] x25: 0000000000000000 x24: 0000000000000000
[ 7654.093031] x23: 0000000000000000 x22: 0000000000000000
[ 7654.098326] x21: 0000000000400740 x20: 0000000000000000
[ 7654.103620] x19: 0000000000000000 x18: 0000000000000000
[ 7654.108915] x17: 0000007fa0c8f698 x16: 0000007fa0d60000
[ 7654.114210] x15: 0000000000000001 x14: 0000000000000000
[ 7654.119505] x13: 0000007fa0d77a18 x12: 0000000000000018
[ 7654.124800] x11: 0000000000000001 x10: 0000007fa0d4f517
[ 7654.130095] x9 : 0000007fa0d77a08 x8 : 0000000000000040
[ 7654.135389] x7 : 000000000000000a x6 : 000000000000000a
[ 7654.140684] x5 : 0000007fa0d36b6f x4 : 0000007fa0d4f951
[ 7654.145979] x3 : 0000000000000000 x2 : 36bc912578986b49
[ 7654.151274] x1 : 0000007fa0d756c0 x0 : 000000ff41ac4d90
[ 7654.156568]
Segmentation fault
-------------------------------
Note that the program shows two different addresses for &iip with the
latter pointing outside the normal memory map. However the test_tls
program works as expected, if you set the LD_BIND_NOW environment variable:
-------------------------------
# LD_BIND_NOW=1 LD_LIBRARY_PATH=/root /root/test_tls
main:
&iip = 0x7f99b606d0
&ii = 0x411048
iip = 0x411048
print_ptrs:
&iip = 0x7f99b606d0
&ii = 0x411048
iip = 0x411048
-------------------------------
Unfortunately this trick does not seem to work for either the
test_res_init program or the ntpd.
Regards,
Christoph Mammitzsch
Hi,
patch applied and pushed,
Waldemar
Petar Jovanovic wrote,
> Hi All,
>
> The previous patch to fix generic memmove() was incorrect even though it
> fixed issues with the tests. The comments in the memmove() function and
> different failing test cases misled me to believe the call to memcopy()
> was wrongly conditioned by __ARCH_HAS_BWD_MEMCPY__. It was not.
>
> This generic memmove implementation assumes that memcpy does forward
> copying and that no issues could be seen in this case. However, at least
> MIPS arch has an optimized memcpy that uses prefetching and that
> implementation does not work correctly for overlapping regions.
>
> So, my suggestions is that for now we skip memcpy() calls for MIPS, and
> if more arches in future come across this, we can unify it (same as it
> was done for __ARCH_HAS_BWD_MEMCPY__).
>
> Sorry for not fixing this correctly in the first patch already.
>
> Thanks.
>
> Regards,
> Petar
>
> Petar Jovanovic (1):
> mips: avoid calling memcpy() from memmove() for MIPS arch
>
> libc/string/generic/memmove.c | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
>
> --
> 2.17.1
>
Summary:
Recent arch do not support Legacy.
Thus they don't define ARCH_HAS_DEPRECATED_SYSCALLS
But this led to per-arch headers not being installed and common-generic ones taking precedence.
So it was impossible to declare arch-specific statfs.h for instance, to force 64-bit mode only.
This was leading to the following situation to happen:
1/ an application compiles (say without -D_FILE_OFFSET_BITS set)
it therefore uses struct statfs from libc/sysdeps/linux/common-generic/bits/statfs.h
where f_type and f_bsize fields are U32: https://elixir.bootlin.com/uclibc-ng/latest/source/libc/sysdeps/linux/commo…
2/ application calls "statfs"
3/ uClibc issues "statfs64" syscall (because __NR_statfs64 is defined and __NR_statfs is undefined):
https://elixir.bootlin.com/uclibc-ng/latest/source/libc/sysdeps/linux/commo…
4/ if Linux kernel port is not defining CONFIG_COMPAT, it calls do_statfs_native
https://elixir.bootlin.com/linux/latest/source/fs/statfs.c#L195
5/ it does copy_to_user of the size of struct statfs defined in the kernel source tree:
https://elixir.bootlin.com/linux/latest/source/fs/statfs.c#L161
6/ Generic struct statfs in the kernel is defined like this:
https://elixir.bootlin.com/linux/latest/source/include/uapi/asm-generic/sta…
f_type and f_bsize fields are long (64 bits) for 64-bit archs.
7/ memory corruption occurs because of this mismatch
Solution:
Allow to not define __ARCH_HAS_DEPRECATED_SYSCALLS__ *and* declare its own arch-specific statfs.h header, matching the kernel one.
(for instance with f_type and f_bsize defined as long)
Does this change break other archs?
This change allows headers in libc/sysdeps/linux/<ARCH>/bits/ to override ones in libc/sysdeps/linux/common-generic/bits/
The only arch which does not define __ARCH_HAS_DEPRECATED_SYSCALLS__ *and* has a header in libc/sysdeps/linux/<ARCH>/bits/ which can conflict with one in libc/sysdeps/linux/common-generic/bits/
is c6x.
The file that can override is ../libc/sysdeps/linux/c6x/bits/kernel_stat.h
This, btw, means that, today, this file is there and is not used (during compilation, GNU Make overrides the rule):
Makefile.in:152: warning: overriding recipe for target `include/bits/kernel_stat.h'
Makefile.in:148: warning: ignoring old recipe for target `include/bits/kernel_stat.h'
I was not able to compile uClibc with the only binary toolchain I found for c6x arch (gcc-4.5.1 from code sourcery: https://sourcery.mentor.com/GNUToolchain/release1882)
However, I can tell that c6x's kernel_stat.h only defines two structs: kernel_stat and kernel_stat64: https://elixir.bootlin.com/uclibc-ng/latest/source/libc/sysdeps/linux/c6x/b…
And I can also tell that those structs are only used when using xstat conversion functions (__xstat32_conv / xstat_conv) which are only used and present in the __ARCH_HAS_DEPRECATED_SYSCALLS__ == y case.
However, c6x does not define __ARCH_HAS_DEPRECATED_SYSCALLS__
So I think I can say that this change does not affect c6x nor other archs.
---
Makefile.in | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Makefile.in b/Makefile.in
index 1754040..16ee9ee 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -144,14 +144,14 @@ $(top_builddir)include/dl-osinfo.h $(top_builddir)include/not-cancel.h:
$(ALL_HEADERS_BITS_COMMON):
$(do_ln) $(call rel_srcdir)libc/sysdeps/linux/common/bits/$(@F) $@
-$(ALL_HEADERS_BITS_ARCH):
- $(do_ln) $(call rel_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/bits/$(@F) $@
-
ifneq ($(ARCH_HAS_DEPRECATED_SYSCALLS),y)
$(ALL_HEADERS_BITS_COMMON_NO_LEGACY):
$(do_ln) $(call rel_srcdir)libc/sysdeps/linux/common-generic/bits/$(@F) $@
endif
+$(ALL_HEADERS_BITS_ARCH):
+ $(do_ln) $(call rel_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/bits/$(@F) $@
+
ifneq ($(TARGET_SUBARCH),)
$(ALL_HEADERS_BITS_SUBARCH):
$(do_ln) $(call rel_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/bits/$(TARGET_SUBARCH)/$(@F) $@
--
1.8.3.1