From: Carlos Santos <unixmania(a)gmail.com>
The return type of syscall() is long so __syscall_error, which is jumped
to by syscall handlers to stash an error number into errno, must return
long too otherwhise it returs 4294967295L instead of -1L. For example,
syscall for x86_64 is defined in libc/sysdeps/linux/x86_64/syscall.S as
syscall:
movq %rdi, %rax /* Syscall number -> rax. */
movq %rsi, %rdi /* shift arg1 - arg5. */
movq %rdx, %rsi
movq %rcx, %rdx
movq %r8, %r10
movq %r9, %r8
movq 8(%rsp),%r9 /* arg6 is on the stack. */
syscall /* Do the system call. */
cmpq $-4095, %rax /* Check %rax for error. */
jae __syscall_error /* Branch forward if it failed. */
ret /* Return to caller. */
In libc/sysdeps/linux/x86_64/__syscall_error.c, __syscall_error is
defined as
int __syscall_error(void) attribute_hidden;
int __syscall_error(void)
{
register int err_no __asm__ ("%rcx");
__asm__ ("mov %rax, %rcx\n\t"
"neg %rcx");
__set_errno(err_no);
return -1;
}
So __syscall_error returns -1 as a 32-bit int in a 64-bit register, %rax
(0x00000000ffffffff, whose decimal value is decimal 4294967295) and a
test like this always returns false:
if (syscall(number, ...) == -1)
foo();
Fix the error by making __syscall_error return a long, like syscall().
The problem can be circumvented by the caller by coercing the returned
value to int before comparing it to -1:
if ((int) syscall(number, ...) == -1)
foo();
The same problem probably occurs on other 64-bit systems but so far only
x86_64 was tested, so this change must be considered experimental.
Signed-off-by: Carlos Santos <unixmania(a)gmail.com>
---
libc/sysdeps/linux/aarch64/__syscall_error.c | 4 ++--
libc/sysdeps/linux/alpha/__syscall_error.c | 2 +-
libc/sysdeps/linux/arc/__syscall_error.c | 2 +-
libc/sysdeps/linux/arm/__syscall_error.c | 4 ++--
libc/sysdeps/linux/csky/__syscall_error.c | 2 +-
libc/sysdeps/linux/csky/clone.c | 2 +-
libc/sysdeps/linux/frv/sysdep.c | 2 +-
libc/sysdeps/linux/hppa/__syscall_error.c | 4 ++--
libc/sysdeps/linux/i386/__syscall_error.c | 4 ++--
libc/sysdeps/linux/ia64/__syscall_error.c | 4 ++--
libc/sysdeps/linux/m68k/__syscall_error.c | 4 ++--
libc/sysdeps/linux/metag/__syscall_error.c | 4 ++--
libc/sysdeps/linux/microblaze/__syscall_error.c | 4 ++--
libc/sysdeps/linux/mips/__syscall_error.c | 4 ++--
libc/sysdeps/linux/nds32/__syscall_error.c | 4 ++--
libc/sysdeps/linux/nios2/__syscall_error.c | 4 ++--
libc/sysdeps/linux/or1k/__syscall_error.c | 4 ++--
libc/sysdeps/linux/powerpc/__syscall_error.c | 4 ++--
libc/sysdeps/linux/riscv64/__syscall_error.c | 4 ++--
libc/sysdeps/linux/sparc/__syscall_error.c | 4 ++--
libc/sysdeps/linux/sparc64/__syscall_error.c | 4 ++--
libc/sysdeps/linux/tile/__syscall_error.c | 2 +-
libc/sysdeps/linux/x86_64/__syscall_error.c | 4 ++--
libc/sysdeps/linux/xtensa/__syscall_error.c | 4 ++--
libpthread/nptl/sysdeps/unix/sysv/linux/__syscall_error.c | 4 ++--
25 files changed, 44 insertions(+), 44 deletions(-)
diff --git a/libc/sysdeps/linux/aarch64/__syscall_error.c b/libc/sysdeps/linux/aarch64/__syscall_error.c
index 2b642e816..c682aae49 100644
--- a/libc/sysdeps/linux/aarch64/__syscall_error.c
+++ b/libc/sysdeps/linux/aarch64/__syscall_error.c
@@ -10,8 +10,8 @@
/* This routine is jumped to by all the syscall handlers, to stash
* an error number into errno. */
-int __syscall_error(int err_no) attribute_hidden;
-int __syscall_error(int err_no)
+long __syscall_error(int err_no) attribute_hidden;
+long __syscall_error(int err_no)
{
__set_errno(-err_no);
return -1;
diff --git a/libc/sysdeps/linux/alpha/__syscall_error.c b/libc/sysdeps/linux/alpha/__syscall_error.c
index 7c081f3b5..c986e484d 100644
--- a/libc/sysdeps/linux/alpha/__syscall_error.c
+++ b/libc/sysdeps/linux/alpha/__syscall_error.c
@@ -8,7 +8,7 @@
/* This routine is jumped to by all the syscall handlers, to stash
an error number into errno. */
-int attribute_hidden __syscall_error (void)
+long attribute_hidden __syscall_error (void)
{
register int err_no __asm__("$0");
__set_errno (err_no);
diff --git a/libc/sysdeps/linux/arc/__syscall_error.c b/libc/sysdeps/linux/arc/__syscall_error.c
index 962d743e4..7f30485a8 100644
--- a/libc/sysdeps/linux/arc/__syscall_error.c
+++ b/libc/sysdeps/linux/arc/__syscall_error.c
@@ -8,7 +8,7 @@
#include <errno.h>
#include <sys/syscall.h>
-int __syscall_error(int err_no)
+long __syscall_error(int err_no)
{
__set_errno(-err_no);
return -1;
diff --git a/libc/sysdeps/linux/arm/__syscall_error.c b/libc/sysdeps/linux/arm/__syscall_error.c
index 2b642e816..c682aae49 100644
--- a/libc/sysdeps/linux/arm/__syscall_error.c
+++ b/libc/sysdeps/linux/arm/__syscall_error.c
@@ -10,8 +10,8 @@
/* This routine is jumped to by all the syscall handlers, to stash
* an error number into errno. */
-int __syscall_error(int err_no) attribute_hidden;
-int __syscall_error(int err_no)
+long __syscall_error(int err_no) attribute_hidden;
+long __syscall_error(int err_no)
{
__set_errno(-err_no);
return -1;
diff --git a/libc/sysdeps/linux/csky/__syscall_error.c b/libc/sysdeps/linux/csky/__syscall_error.c
index cc1fb5977..c6a4a14eb 100644
--- a/libc/sysdeps/linux/csky/__syscall_error.c
+++ b/libc/sysdeps/linux/csky/__syscall_error.c
@@ -8,7 +8,7 @@
#include <errno.h>
#include <features.h>
-int __syscall_error(int err_no)
+long __syscall_error(int err_no)
{
__set_errno(-err_no);
return -1;
diff --git a/libc/sysdeps/linux/csky/clone.c b/libc/sysdeps/linux/csky/clone.c
index 991cb8962..f0fcc257b 100644
--- a/libc/sysdeps/linux/csky/clone.c
+++ b/libc/sysdeps/linux/csky/clone.c
@@ -9,7 +9,7 @@
#include <sysdep.h>
#include <unistd.h>
-extern int __syscall_error(int err_no);
+extern long __syscall_error(int err_no);
extern int __csky_clone (
int flags,
diff --git a/libc/sysdeps/linux/frv/sysdep.c b/libc/sysdeps/linux/frv/sysdep.c
index bfae12100..28beb418f 100644
--- a/libc/sysdeps/linux/frv/sysdep.c
+++ b/libc/sysdeps/linux/frv/sysdep.c
@@ -19,7 +19,7 @@
/* This routine is jumped to by all the syscall handlers, to stash
an error number into errno. */
-int __syscall_error (int err_no)
+long __syscall_error (int err_no)
{
__set_errno (-err_no);
return -1;
diff --git a/libc/sysdeps/linux/hppa/__syscall_error.c b/libc/sysdeps/linux/hppa/__syscall_error.c
index 5e109a83b..af26cf6ab 100644
--- a/libc/sysdeps/linux/hppa/__syscall_error.c
+++ b/libc/sysdeps/linux/hppa/__syscall_error.c
@@ -10,8 +10,8 @@
/* This routine is jumped to by all the syscall handlers, to stash
* an error number into errno. */
-int __syscall_error(int err_no) attribute_hidden;
-int __syscall_error(int err_no)
+long __syscall_error(int err_no) attribute_hidden;
+long __syscall_error(int err_no)
{
__set_errno(err_no);
return -1;
diff --git a/libc/sysdeps/linux/i386/__syscall_error.c b/libc/sysdeps/linux/i386/__syscall_error.c
index 36946bc6d..102ebbedb 100644
--- a/libc/sysdeps/linux/i386/__syscall_error.c
+++ b/libc/sysdeps/linux/i386/__syscall_error.c
@@ -25,8 +25,8 @@
#include <errno.h>
#include <features.h>
-int __syscall_error(void) attribute_hidden;
-int __syscall_error(void)
+long __syscall_error(void) attribute_hidden;
+long __syscall_error(void)
{
register int eax __asm__ ("%eax");
int _errno = -eax;
diff --git a/libc/sysdeps/linux/ia64/__syscall_error.c b/libc/sysdeps/linux/ia64/__syscall_error.c
index 0727b2b53..cc2b13450 100644
--- a/libc/sysdeps/linux/ia64/__syscall_error.c
+++ b/libc/sysdeps/linux/ia64/__syscall_error.c
@@ -10,8 +10,8 @@
/* This routine is jumped to by all the syscall handlers, to stash
* an error number into errno. */
-int __syscall_error(void) attribute_hidden;
-int __syscall_error(void)
+long __syscall_error(void) attribute_hidden;
+long __syscall_error(void)
{
register int err_no __asm__("%r8");
__set_errno(err_no);
diff --git a/libc/sysdeps/linux/m68k/__syscall_error.c b/libc/sysdeps/linux/m68k/__syscall_error.c
index a29f6ffd6..2d2677521 100644
--- a/libc/sysdeps/linux/m68k/__syscall_error.c
+++ b/libc/sysdeps/linux/m68k/__syscall_error.c
@@ -10,8 +10,8 @@
/* This routine is jumped to by all the syscall handlers, to stash
* an error number into errno. */
-int __syscall_error(void) attribute_hidden;
-int __syscall_error(void)
+long __syscall_error(void) attribute_hidden;
+long __syscall_error(void)
{
register int err_no __asm__("%d0");
__set_errno(-err_no);
diff --git a/libc/sysdeps/linux/metag/__syscall_error.c b/libc/sysdeps/linux/metag/__syscall_error.c
index f97cd0126..3e82abe0d 100644
--- a/libc/sysdeps/linux/metag/__syscall_error.c
+++ b/libc/sysdeps/linux/metag/__syscall_error.c
@@ -10,8 +10,8 @@
/* This routine is jumped to by all the syscall handlers, to stash
* an error number into errno. */
-int __syscall_error(int err_no) attribute_hidden;
-int __syscall_error(int err_no)
+long __syscall_error(int err_no) attribute_hidden;
+long __syscall_error(int err_no)
{
__set_errno(-err_no);
return -1;
diff --git a/libc/sysdeps/linux/microblaze/__syscall_error.c b/libc/sysdeps/linux/microblaze/__syscall_error.c
index 2b642e816..c682aae49 100644
--- a/libc/sysdeps/linux/microblaze/__syscall_error.c
+++ b/libc/sysdeps/linux/microblaze/__syscall_error.c
@@ -10,8 +10,8 @@
/* This routine is jumped to by all the syscall handlers, to stash
* an error number into errno. */
-int __syscall_error(int err_no) attribute_hidden;
-int __syscall_error(int err_no)
+long __syscall_error(int err_no) attribute_hidden;
+long __syscall_error(int err_no)
{
__set_errno(-err_no);
return -1;
diff --git a/libc/sysdeps/linux/mips/__syscall_error.c b/libc/sysdeps/linux/mips/__syscall_error.c
index 5e109a83b..af26cf6ab 100644
--- a/libc/sysdeps/linux/mips/__syscall_error.c
+++ b/libc/sysdeps/linux/mips/__syscall_error.c
@@ -10,8 +10,8 @@
/* This routine is jumped to by all the syscall handlers, to stash
* an error number into errno. */
-int __syscall_error(int err_no) attribute_hidden;
-int __syscall_error(int err_no)
+long __syscall_error(int err_no) attribute_hidden;
+long __syscall_error(int err_no)
{
__set_errno(err_no);
return -1;
diff --git a/libc/sysdeps/linux/nds32/__syscall_error.c b/libc/sysdeps/linux/nds32/__syscall_error.c
index 2aa6903e2..c8e6044a7 100644
--- a/libc/sysdeps/linux/nds32/__syscall_error.c
+++ b/libc/sysdeps/linux/nds32/__syscall_error.c
@@ -8,8 +8,8 @@
/* This routine is jumped to by all the syscall handlers, to stash
* an error number into errno. */
-int __syscall_error(int err_no) attribute_hidden;
-int __syscall_error(int err_no)
+long __syscall_error(int err_no) attribute_hidden;
+long __syscall_error(int err_no)
{
__set_errno(err_no);
return -1;
diff --git a/libc/sysdeps/linux/nios2/__syscall_error.c b/libc/sysdeps/linux/nios2/__syscall_error.c
index 2b642e816..c682aae49 100644
--- a/libc/sysdeps/linux/nios2/__syscall_error.c
+++ b/libc/sysdeps/linux/nios2/__syscall_error.c
@@ -10,8 +10,8 @@
/* This routine is jumped to by all the syscall handlers, to stash
* an error number into errno. */
-int __syscall_error(int err_no) attribute_hidden;
-int __syscall_error(int err_no)
+long __syscall_error(int err_no) attribute_hidden;
+long __syscall_error(int err_no)
{
__set_errno(-err_no);
return -1;
diff --git a/libc/sysdeps/linux/or1k/__syscall_error.c b/libc/sysdeps/linux/or1k/__syscall_error.c
index 1b7e8a394..7d1e09d91 100644
--- a/libc/sysdeps/linux/or1k/__syscall_error.c
+++ b/libc/sysdeps/linux/or1k/__syscall_error.c
@@ -17,11 +17,11 @@
#include <errno.h>
-int __syscall_error (int err_no);
+long __syscall_error (int err_no);
/* This routine is jumped to by all the syscall handlers, to stash
* an error number into errno. */
-int __syscall_error (int err_no)
+long __syscall_error (int err_no)
{
__set_errno (err_no);
return -1;
diff --git a/libc/sysdeps/linux/powerpc/__syscall_error.c b/libc/sysdeps/linux/powerpc/__syscall_error.c
index 5e109a83b..af26cf6ab 100644
--- a/libc/sysdeps/linux/powerpc/__syscall_error.c
+++ b/libc/sysdeps/linux/powerpc/__syscall_error.c
@@ -10,8 +10,8 @@
/* This routine is jumped to by all the syscall handlers, to stash
* an error number into errno. */
-int __syscall_error(int err_no) attribute_hidden;
-int __syscall_error(int err_no)
+long __syscall_error(int err_no) attribute_hidden;
+long __syscall_error(int err_no)
{
__set_errno(err_no);
return -1;
diff --git a/libc/sysdeps/linux/riscv64/__syscall_error.c b/libc/sysdeps/linux/riscv64/__syscall_error.c
index 2b642e816..c682aae49 100644
--- a/libc/sysdeps/linux/riscv64/__syscall_error.c
+++ b/libc/sysdeps/linux/riscv64/__syscall_error.c
@@ -10,8 +10,8 @@
/* This routine is jumped to by all the syscall handlers, to stash
* an error number into errno. */
-int __syscall_error(int err_no) attribute_hidden;
-int __syscall_error(int err_no)
+long __syscall_error(int err_no) attribute_hidden;
+long __syscall_error(int err_no)
{
__set_errno(-err_no);
return -1;
diff --git a/libc/sysdeps/linux/sparc/__syscall_error.c b/libc/sysdeps/linux/sparc/__syscall_error.c
index 5e109a83b..af26cf6ab 100644
--- a/libc/sysdeps/linux/sparc/__syscall_error.c
+++ b/libc/sysdeps/linux/sparc/__syscall_error.c
@@ -10,8 +10,8 @@
/* This routine is jumped to by all the syscall handlers, to stash
* an error number into errno. */
-int __syscall_error(int err_no) attribute_hidden;
-int __syscall_error(int err_no)
+long __syscall_error(int err_no) attribute_hidden;
+long __syscall_error(int err_no)
{
__set_errno(err_no);
return -1;
diff --git a/libc/sysdeps/linux/sparc64/__syscall_error.c b/libc/sysdeps/linux/sparc64/__syscall_error.c
index 5e109a83b..af26cf6ab 100644
--- a/libc/sysdeps/linux/sparc64/__syscall_error.c
+++ b/libc/sysdeps/linux/sparc64/__syscall_error.c
@@ -10,8 +10,8 @@
/* This routine is jumped to by all the syscall handlers, to stash
* an error number into errno. */
-int __syscall_error(int err_no) attribute_hidden;
-int __syscall_error(int err_no)
+long __syscall_error(int err_no) attribute_hidden;
+long __syscall_error(int err_no)
{
__set_errno(err_no);
return -1;
diff --git a/libc/sysdeps/linux/tile/__syscall_error.c b/libc/sysdeps/linux/tile/__syscall_error.c
index a91fdff3a..31cab3799 100644
--- a/libc/sysdeps/linux/tile/__syscall_error.c
+++ b/libc/sysdeps/linux/tile/__syscall_error.c
@@ -6,7 +6,7 @@
#include <errno.h>
#include <features.h>
-int __syscall_error(int err_no)
+long __syscall_error(int err_no)
{
__set_errno(-err_no);
return -1;
diff --git a/libc/sysdeps/linux/x86_64/__syscall_error.c b/libc/sysdeps/linux/x86_64/__syscall_error.c
index 448f50983..7f0f388c4 100644
--- a/libc/sysdeps/linux/x86_64/__syscall_error.c
+++ b/libc/sysdeps/linux/x86_64/__syscall_error.c
@@ -10,8 +10,8 @@
/* This routine is jumped to by all the syscall handlers, to stash
* an error number into errno. */
-int __syscall_error(void) attribute_hidden;
-int __syscall_error(void)
+long __syscall_error(void) attribute_hidden;
+long __syscall_error(void)
{
register int err_no __asm__ ("%rcx");
__asm__ ("mov %rax, %rcx\n\t"
diff --git a/libc/sysdeps/linux/xtensa/__syscall_error.c b/libc/sysdeps/linux/xtensa/__syscall_error.c
index 2b642e816..c682aae49 100644
--- a/libc/sysdeps/linux/xtensa/__syscall_error.c
+++ b/libc/sysdeps/linux/xtensa/__syscall_error.c
@@ -10,8 +10,8 @@
/* This routine is jumped to by all the syscall handlers, to stash
* an error number into errno. */
-int __syscall_error(int err_no) attribute_hidden;
-int __syscall_error(int err_no)
+long __syscall_error(int err_no) attribute_hidden;
+long __syscall_error(int err_no)
{
__set_errno(-err_no);
return -1;
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/__syscall_error.c b/libpthread/nptl/sysdeps/unix/sysv/linux/__syscall_error.c
index 5e109a83b..af26cf6ab 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/__syscall_error.c
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/__syscall_error.c
@@ -10,8 +10,8 @@
/* This routine is jumped to by all the syscall handlers, to stash
* an error number into errno. */
-int __syscall_error(int err_no) attribute_hidden;
-int __syscall_error(int err_no)
+long __syscall_error(int err_no) attribute_hidden;
+long __syscall_error(int err_no)
{
__set_errno(err_no);
return -1;
--
2.18.1
Hi,
what do you think about attached patch to unbreak c-sky for kernel
5.x and gcc 9.2.
Tested in Qemu with static/shared builds.
best regards
Waldemar
This symbol was causing a build failure with the new toolchain. It
looks like it has always been wrong.
The main issue was checking for PIC rather than __PIC__.
Remove all PSEUDO_* macros and ther SYSCALL_ERROR_NAME macro as they are
not needed by uclibc-ng, they are used in glibc for building up syscalls
there, but not here.
Fixes error:
/opt/shorne/software/or1k-linux/bin/../lib/gcc/or1k-linux/9.0.1/../../../../or1k-linux/bin/ld: libc/libc_so.a(or1k_clone.os): pc-relative relocation against dynamic symbol __syscall_error
/opt/shorne/software/or1k-linux/bin/../lib/gcc/or1k-linux/9.0.1/../../../../or1k-linux/bin/ld: final link failed: bad value
Signed-off-by: Stafford Horne <shorne(a)gmail.com>
---
libc/sysdeps/linux/or1k/or1k_clone.S | 8 +++++--
libc/sysdeps/linux/or1k/sysdep.h | 32 ----------------------------
2 files changed, 6 insertions(+), 34 deletions(-)
diff --git a/libc/sysdeps/linux/or1k/or1k_clone.S b/libc/sysdeps/linux/or1k/or1k_clone.S
index a2c16ac9e..2de873a02 100644
--- a/libc/sysdeps/linux/or1k/or1k_clone.S
+++ b/libc/sysdeps/linux/or1k/or1k_clone.S
@@ -71,7 +71,11 @@ L(oldpid):
l.ori r3, r11, 0
L(error):
- l.j SYSCALL_ERROR_NAME
+#ifdef __PIC__
+ l.j plt(__syscall_error)
+#else
+ l.j __syscall_error
+#endif
l.ori r3,r11,0
-PSEUDO_END (__or1k_clone)
+END (__or1k_clone)
diff --git a/libc/sysdeps/linux/or1k/sysdep.h b/libc/sysdeps/linux/or1k/sysdep.h
index 4dba3f2a0..782981c55 100644
--- a/libc/sysdeps/linux/or1k/sysdep.h
+++ b/libc/sysdeps/linux/or1k/sysdep.h
@@ -43,38 +43,6 @@ License along with the GNU C Library; if not, see
l.sys 1; \
l.nop
-#define PSEUDO(name, syscall_name, args) \
- ENTRY (name); \
- DO_CALL(syscall_name); \
- /* if -4096 < ret < 0 holds, it's an error */ \
- l.sfgeui r11, 0xf001; \
- l.bf L(pseudo_end); \
- l.nop
-
-#define PSEUDO_NOERRNO(name, syscall_name, args) \
- ENTRY (name); \
- DO_CALL(syscall_name)
-
-#define PSEUDO_END(name) \
-L(pseudo_end): \
- l.j SYSCALL_ERROR_NAME; \
- l.ori r3,r11,0; \
- END (name)
-
-#define PSEUDO_END_NOERRNO(name) \
- END (name)
-
-#ifndef PIC
-/* For static code, on error jump to __syscall_error directly. */
-# define SYSCALL_ERROR_NAME __syscall_error
-#elif NOT_IN_libc
-/* Use the internal name for libc/libpthread shared objects. */
-# define SYSCALL_ERROR_NAME __GI___syscall_error
-#else
-/* Otherwise, on error do a full PLT jump. */
-# define SYSCALL_ERROR_NAME plt(__syscall_error)
-#endif
-
/* Make use of .size directive. */
#define ASM_SIZE_DIRECTIVE(name) .size name,.-name;
--
2.21.0
Hello,
I would like to know if there is consensus on the fact that this program
hanging on a deadlock is a uClibc-ng bug: https://pastebin.com/11qLsTW5
I've asked people to try this on several arch/libc combination, it works
well (no hang) on:
* x86_64/glibc
* x86_64/musl
* armv7l/musl
Also, I've run the puts.c test (linked above) on 3 archs with uClibc-ng,
it fails (hangs) on:
* or1k/uClibc-ng
* mips32r6/uClibc-ng
* k1c/uClibc-ng (port not completely published yet)
See failure logs + strace -f of what happens when hanging:
https://mypads.framapad.org/mypads/?/mypads/group/uclibc-ng-10be37ap/pad/vi…
My understanding of the issue is that:
puts, and possibly other libc functions, are taking a lock (
https://elixir.bootlin.com/uclibc-ng/latest/source/libc/stdio/puts.c#L17
) and end up calling write() which is a cancellation point. (
https://elixir.bootlin.com/uclibc-ng/latest/source/libc/stdio/_stdio.h#L150
)
So, if a thread is canceled, is asynchronous mode (which is the default
one), and the cancelation is triggered by the write() inside the puts(),
then the thread will unwind and exit without unlocking the puts lock.
Then, any other thread calling puts() will hang indefinetely (and hang
other threads if it hangs with locks held...).
My understanding of what can be done to fix this issue:
1/ Either make puts a non cancelation point (see man 7 pthreads, puts is
not listed in mandatory cancelation point, only in "may"). For instance
it is not a cancelation point in glibc.
2/ Or keep puts as a cancelation point and fix the puts code so that it
releases the lock upon cancelation (using pthread_cleanup_push/pop for
instance)
In case people think this is indeed a bug, here are examples of code
fixes that I have in mind, please don't hesitate to comment or/and
propose something else:
1/ https://pastebin.com/ePsWJzdi
2/ https://pastebin.com/5EA4RedS
One problem of those fixes is that we need to identify all libc
functions that take a lock and call a cancellable function and apply
such kind of fixes... This is not easy and a bit painful.
Thanks!
Regards,
--
Yann Sionneau
The internal heap structures were not protected properly in
memalign(). If multiple threads were concurrently allocating memory and
one of them were requesting aligned memory via valloc,memalign or
posix_memalign the internal heap data structures could be corrupted.
Signed-off-by: Kjetil Oftedal <oftedal(a)gmail.com>
---
libc/stdlib/malloc/memalign.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/libc/stdlib/malloc/memalign.c b/libc/stdlib/malloc/memalign.c
index 74d5dbd..0d3de67 100644
--- a/libc/stdlib/malloc/memalign.c
+++ b/libc/stdlib/malloc/memalign.c
@@ -77,7 +77,9 @@ memalign (size_t alignment, size_t size)
init_size = addr - tot_addr;
}
+ __heap_lock (&__malloc_heap_lock);
__heap_free (heap, base, init_size);
+ __heap_unlock (&__malloc_heap_lock);
/* Remember that we've freed the initial part of MEM. */
base += init_size;
@@ -85,9 +87,11 @@ memalign (size_t alignment, size_t size)
/* Return the end part of MEM to the heap, unless it's too small. */
end_addr = addr + size;
- if (end_addr + MALLOC_REALLOC_MIN_FREE_SIZE < tot_end_addr)
+ if (end_addr + MALLOC_REALLOC_MIN_FREE_SIZE < tot_end_addr) {
+ __heap_lock (&__malloc_heap_lock);
__heap_free (heap, (void *)end_addr, tot_end_addr - end_addr);
- else
+ __heap_unlock (&__malloc_heap_lock);
+ } else
/* We didn't free the end, so include it in the size. */
end_addr = tot_end_addr;
--
1.7.9.5
Hi Waldemar,
I discovered an issue with uClibc and binutils 2.32 and gcc 9.1 or 9.2.
LD libuClibc-1.0.31.so
/opt/openrisc--uclibc--bleeding-edge-1/lib/gcc/or1k-buildroot-linux-uclibc/9.2.0/../../../../or1k-buildroot-linux-uclibc/bin/ld:
libc/libc_so.a(or1k_clone.os): pc-relative relocation against dynamic symbol
__syscall_error
See:
https://gitlab.com/kubu93/toolchains-builder/-/jobs/270854456
This error message come from a new check in binutils 2.32.x:
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commitdiff;h=f2c…
With binutils 2.30.x and 2.31.x, I have another assembler error:
Error: junk at end of line `l.movhi r17,gotoffha(.LC0)'
ork1 support was added to gcc 9.x and enabled into Buildroot recently.
https://git.buildroot.net/buildroot/commit/?id=da70a55a1955ff673e0110bacb3d…
I remember doing a test with qemu_or1k_defconfig before gcc 9.1 was released but
I don't remember if it was with musl or uClibc-ng... It should be with uClibc-ng
but I didn't trigged such error.
Thoughts ?
Best regards,
Romain
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