Browse Source

Make __syscall_error return long, as expected by syscall() callers

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@gmail.com>
Carlos Santos 4 years ago
parent
commit
01e863c89f

+ 2 - 2
libc/sysdeps/linux/aarch64/__syscall_error.c

@@ -10,8 +10,8 @@
 
 
 /* This routine is jumped to by all the syscall handlers, to stash
 /* This routine is jumped to by all the syscall handlers, to stash
  * an error number into errno.  */
  * 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);
 	__set_errno(-err_no);
 	return -1;
 	return -1;

+ 1 - 1
libc/sysdeps/linux/alpha/__syscall_error.c

@@ -8,7 +8,7 @@
 
 
 /* This routine is jumped to by all the syscall handlers, to stash
 /* This routine is jumped to by all the syscall handlers, to stash
    an error number into errno.  */
    an error number into errno.  */
-int attribute_hidden __syscall_error (void)
+long attribute_hidden __syscall_error (void)
 {
 {
 	register int err_no __asm__("$0");
 	register int err_no __asm__("$0");
 	__set_errno (err_no);
 	__set_errno (err_no);

+ 1 - 1
libc/sysdeps/linux/arc/__syscall_error.c

@@ -8,7 +8,7 @@
 #include <errno.h>
 #include <errno.h>
 #include <sys/syscall.h>
 #include <sys/syscall.h>
 
 
-int __syscall_error(int err_no)
+long __syscall_error(int err_no)
 {
 {
 	__set_errno(-err_no);
 	__set_errno(-err_no);
 	return -1;
 	return -1;

+ 1 - 1
libc/sysdeps/linux/arc/bits/syscalls.h

@@ -34,7 +34,7 @@
 /* ldso doesn't have real errno */
 /* ldso doesn't have real errno */
 #define ERRNO_ERRANDS(_sys_result)
 #define ERRNO_ERRANDS(_sys_result)
 #else /* !IS_IN_rtld */
 #else /* !IS_IN_rtld */
-extern int __syscall_error (int);
+extern long __syscall_error (int);
 #ifndef IS_IN_libc
 #ifndef IS_IN_libc
 /* Inter-libc callers use PLT */
 /* Inter-libc callers use PLT */
 #define CALL_ERRNO_SETTER   "bl   __syscall_error@plt    \n\t"
 #define CALL_ERRNO_SETTER   "bl   __syscall_error@plt    \n\t"

+ 2 - 2
libc/sysdeps/linux/arm/__syscall_error.c

@@ -10,8 +10,8 @@
 
 
 /* This routine is jumped to by all the syscall handlers, to stash
 /* This routine is jumped to by all the syscall handlers, to stash
  * an error number into errno.  */
  * 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);
 	__set_errno(-err_no);
 	return -1;
 	return -1;

+ 1 - 1
libc/sysdeps/linux/csky/__syscall_error.c

@@ -8,7 +8,7 @@
 #include <errno.h>
 #include <errno.h>
 #include <features.h>
 #include <features.h>
 
 
-int __syscall_error(int err_no)
+long __syscall_error(int err_no)
 {
 {
 	__set_errno(-err_no);
 	__set_errno(-err_no);
 	return -1;
 	return -1;

+ 1 - 1
libc/sysdeps/linux/csky/clone.c

@@ -9,7 +9,7 @@
 #include <sysdep.h>
 #include <sysdep.h>
 #include <unistd.h>
 #include <unistd.h>
 
 
-extern int __syscall_error(int err_no);
+extern long __syscall_error(int err_no);
 
 
 extern int __csky_clone (
 extern int __csky_clone (
   int flags,
   int flags,

+ 1 - 1
libc/sysdeps/linux/frv/sysdep.c

@@ -19,7 +19,7 @@
 
 
 /* This routine is jumped to by all the syscall handlers, to stash
 /* This routine is jumped to by all the syscall handlers, to stash
    an error number into errno.  */
    an error number into errno.  */
-int __syscall_error (int err_no)
+long __syscall_error (int err_no)
 {
 {
   __set_errno (-err_no);
   __set_errno (-err_no);
   return -1;
   return -1;

+ 2 - 2
libc/sysdeps/linux/hppa/__syscall_error.c

@@ -10,8 +10,8 @@
 
 
 /* This routine is jumped to by all the syscall handlers, to stash
 /* This routine is jumped to by all the syscall handlers, to stash
  * an error number into errno.  */
  * 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);
 	__set_errno(err_no);
 	return -1;
 	return -1;

+ 2 - 2
libc/sysdeps/linux/i386/__syscall_error.c

@@ -25,8 +25,8 @@
 #include <errno.h>
 #include <errno.h>
 #include <features.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");
 	register int eax __asm__ ("%eax");
 	int _errno = -eax;
 	int _errno = -eax;

+ 2 - 2
libc/sysdeps/linux/ia64/__syscall_error.c

@@ -10,8 +10,8 @@
 
 
 /* This routine is jumped to by all the syscall handlers, to stash
 /* This routine is jumped to by all the syscall handlers, to stash
  * an error number into errno.  */
  * 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");
 	register int err_no __asm__("%r8");
 	__set_errno(err_no);
 	__set_errno(err_no);

+ 2 - 2
libc/sysdeps/linux/m68k/__syscall_error.c

@@ -10,8 +10,8 @@
 
 
 /* This routine is jumped to by all the syscall handlers, to stash
 /* This routine is jumped to by all the syscall handlers, to stash
  * an error number into errno.  */
  * 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");
 	register int err_no __asm__("%d0");
 	__set_errno(-err_no);
 	__set_errno(-err_no);

+ 2 - 2
libc/sysdeps/linux/metag/__syscall_error.c

@@ -10,8 +10,8 @@
 
 
 /* This routine is jumped to by all the syscall handlers, to stash
 /* This routine is jumped to by all the syscall handlers, to stash
  * an error number into errno.  */
  * 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);
 	__set_errno(-err_no);
 	return -1;
 	return -1;

+ 2 - 2
libc/sysdeps/linux/microblaze/__syscall_error.c

@@ -10,8 +10,8 @@
 
 
 /* This routine is jumped to by all the syscall handlers, to stash
 /* This routine is jumped to by all the syscall handlers, to stash
  * an error number into errno.  */
  * 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);
 	__set_errno(-err_no);
 	return -1;
 	return -1;

+ 2 - 2
libc/sysdeps/linux/mips/__syscall_error.c

@@ -10,8 +10,8 @@
 
 
 /* This routine is jumped to by all the syscall handlers, to stash
 /* This routine is jumped to by all the syscall handlers, to stash
  * an error number into errno.  */
  * 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);
 	__set_errno(err_no);
 	return -1;
 	return -1;

+ 2 - 2
libc/sysdeps/linux/nds32/__syscall_error.c

@@ -8,8 +8,8 @@
 
 
 /* This routine is jumped to by all the syscall handlers, to stash
 /* This routine is jumped to by all the syscall handlers, to stash
  * an error number into errno.  */
  * 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);
 	__set_errno(err_no);
 	return -1;
 	return -1;

+ 2 - 2
libc/sysdeps/linux/nios2/__syscall_error.c

@@ -10,8 +10,8 @@
 
 
 /* This routine is jumped to by all the syscall handlers, to stash
 /* This routine is jumped to by all the syscall handlers, to stash
  * an error number into errno.  */
  * 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);
 	__set_errno(-err_no);
 	return -1;
 	return -1;

+ 2 - 2
libc/sysdeps/linux/or1k/__syscall_error.c

@@ -17,11 +17,11 @@
 
 
 #include <errno.h>
 #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
 /* This routine is jumped to by all the syscall handlers, to stash
  * an error number into errno.  */
  * an error number into errno.  */
-int __syscall_error (int err_no)
+long __syscall_error (int err_no)
 {
 {
 	__set_errno (err_no);
 	__set_errno (err_no);
 	return -1;
 	return -1;

+ 2 - 2
libc/sysdeps/linux/powerpc/__syscall_error.c

@@ -10,8 +10,8 @@
 
 
 /* This routine is jumped to by all the syscall handlers, to stash
 /* This routine is jumped to by all the syscall handlers, to stash
  * an error number into errno.  */
  * 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);
 	__set_errno(err_no);
 	return -1;
 	return -1;

+ 2 - 2
libc/sysdeps/linux/riscv64/__syscall_error.c

@@ -10,8 +10,8 @@
 
 
 /* This routine is jumped to by all the syscall handlers, to stash
 /* This routine is jumped to by all the syscall handlers, to stash
  * an error number into errno.  */
  * 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);
 	__set_errno(-err_no);
 	return -1;
 	return -1;

+ 2 - 2
libc/sysdeps/linux/sparc/__syscall_error.c

@@ -10,8 +10,8 @@
 
 
 /* This routine is jumped to by all the syscall handlers, to stash
 /* This routine is jumped to by all the syscall handlers, to stash
  * an error number into errno.  */
  * 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);
 	__set_errno(err_no);
 	return -1;
 	return -1;

+ 2 - 2
libc/sysdeps/linux/sparc64/__syscall_error.c

@@ -10,8 +10,8 @@
 
 
 /* This routine is jumped to by all the syscall handlers, to stash
 /* This routine is jumped to by all the syscall handlers, to stash
  * an error number into errno.  */
  * 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);
 	__set_errno(err_no);
 	return -1;
 	return -1;

+ 1 - 1
libc/sysdeps/linux/tile/__syscall_error.c

@@ -6,7 +6,7 @@
 #include <errno.h>
 #include <errno.h>
 #include <features.h>
 #include <features.h>
 
 
-int __syscall_error(int err_no)
+long __syscall_error(int err_no)
 {
 {
 	__set_errno(-err_no);
 	__set_errno(-err_no);
 	return -1;
 	return -1;

+ 2 - 2
libc/sysdeps/linux/x86_64/__syscall_error.c

@@ -10,8 +10,8 @@
 
 
 /* This routine is jumped to by all the syscall handlers, to stash
 /* This routine is jumped to by all the syscall handlers, to stash
  * an error number into errno.  */
  * 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");
 	register int err_no __asm__ ("%rcx");
 	__asm__ ("mov %rax, %rcx\n\t"
 	__asm__ ("mov %rax, %rcx\n\t"

+ 2 - 2
libc/sysdeps/linux/xtensa/__syscall_error.c

@@ -10,8 +10,8 @@
 
 
 /* This routine is jumped to by all the syscall handlers, to stash
 /* This routine is jumped to by all the syscall handlers, to stash
  * an error number into errno.  */
  * 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);
 	__set_errno(-err_no);
 	return -1;
 	return -1;

+ 2 - 2
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
 /* This routine is jumped to by all the syscall handlers, to stash
  * an error number into errno.  */
  * 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);
 	__set_errno(err_no);
 	return -1;
 	return -1;