[PATCH] Add SYSCALL_LONG/SYSCALL_ULONG to pass long to syscall [BZ #25810]

H.J. Lu hjl.tools@gmail.com
Fri Apr 10 21:22:49 GMT 2020


X32 has 32-bit long and pointer with 64-bit off_t.  Since x32 psABI
requires that pointers passed in registers must be zero-extended to
64bit, x32 can share many syscall interfaces with LP64.  When a LP64
syscall with long and unsigned long arguments is used for x32, these
arguments must be properly extended to 64-bit.  Otherwise if the upper
32 bits of the register have undefined value, such a syscall will be
rejected by kernel.

For inline syscalls, SYSCALL_LONG and SYSCALL_ULONG are introduced as
wrappers for long and unsigned long arguments.

For syscalls implemented in assembly codes, 'U' is added to syscall
signature key letters for unsigned long.  SYSCALL_ULONG_ARG_1 and
SYSCALL_ULONG_ARG_2 are passed to syscall-template.S for the first
and the second unsigned long arguments.  They are used by x32 to
zero-extend 32-bit arguments to 64 bits.

Tested on i386, x86-64 and 32 as well as with build-many-glibcs.py.
---
 misc/Makefile                                 |   2 +-
 misc/tst-syscalls.c                           | 146 ++++++++++++++++++
 sysdeps/unix/make-syscalls.sh                 |  88 +++++++++++
 sysdeps/unix/syscall-template.S               |  37 ++++-
 sysdeps/unix/sysv/linux/copy_file_range.c     |   2 +-
 sysdeps/unix/sysv/linux/getcwd.c              |   2 +-
 sysdeps/unix/sysv/linux/getdents.c            |   3 +-
 sysdeps/unix/sysv/linux/getdents64.c          |   6 +-
 sysdeps/unix/sysv/linux/getentropy.c          |   4 +-
 sysdeps/unix/sysv/linux/getrandom.c           |   3 +-
 sysdeps/unix/sysv/linux/mlock2.c              |   8 +-
 sysdeps/unix/sysv/linux/mmap64.c              |   7 +-
 sysdeps/unix/sysv/linux/mq_timedreceive.c     |  12 +-
 sysdeps/unix/sysv/linux/mq_timedsend.c        |  14 +-
 sysdeps/unix/sysv/linux/msgrcv.c              |   7 +-
 sysdeps/unix/sysv/linux/msgsnd.c              |   7 +-
 sysdeps/unix/sysv/linux/msync.c               |   2 +-
 sysdeps/unix/sysv/linux/pkey_mprotect.c       |   3 +-
 sysdeps/unix/sysv/linux/pread.c               |   3 +-
 sysdeps/unix/sysv/linux/pread64.c             |   3 +-
 sysdeps/unix/sysv/linux/pread64_nocancel.c    |   3 +-
 sysdeps/unix/sysv/linux/pwrite.c              |   3 +-
 sysdeps/unix/sysv/linux/pwrite64.c            |   3 +-
 sysdeps/unix/sysv/linux/read.c                |   2 +-
 sysdeps/unix/sysv/linux/read_nocancel.c       |   2 +-
 sysdeps/unix/sysv/linux/readahead.c           |   2 +-
 sysdeps/unix/sysv/linux/recv.c                |   7 +-
 sysdeps/unix/sysv/linux/recvfrom.c            |   8 +-
 sysdeps/unix/sysv/linux/sched_setaffinity.c   |   3 +-
 sysdeps/unix/sysv/linux/semtimedop.c          |   6 +-
 sysdeps/unix/sysv/linux/send.c                |   7 +-
 sysdeps/unix/sysv/linux/sendto.c              |   8 +-
 sysdeps/unix/sysv/linux/shmget.c              |   6 +-
 sysdeps/unix/sysv/linux/splice.c              |   3 +-
 sysdeps/unix/sysv/linux/sysdep.h              |   5 +
 sysdeps/unix/sysv/linux/tee.c                 |   2 +-
 sysdeps/unix/sysv/linux/vmsplice.c            |   2 +-
 sysdeps/unix/sysv/linux/write.c               |   2 +-
 sysdeps/unix/sysv/linux/write_nocancel.c      |   2 +-
 sysdeps/unix/sysv/linux/x86_64/sysdep.h       |  57 +++++--
 .../unix/sysv/linux/x86_64/x32/syscalls.list  |  10 ++
 sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h   |  30 ++++
 42 files changed, 450 insertions(+), 82 deletions(-)
 create mode 100644 misc/tst-syscalls.c

diff --git a/misc/Makefile b/misc/Makefile
index b8fed5783d..67c5237f97 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -87,7 +87,7 @@ tests := tst-dirname tst-tsearch tst-fdset tst-mntent tst-hsearch \
 	 tst-preadvwritev tst-preadvwritev64 tst-makedev tst-empty \
 	 tst-preadvwritev2 tst-preadvwritev64v2 tst-warn-wide \
 	 tst-ldbl-warn tst-ldbl-error tst-dbl-efgcvt tst-ldbl-efgcvt \
-	 tst-mntent-autofs
+	 tst-mntent-autofs tst-syscalls
 
 # Tests which need libdl.
 ifeq (yes,$(build-shared))
diff --git a/misc/tst-syscalls.c b/misc/tst-syscalls.c
new file mode 100644
index 0000000000..d07f03633b
--- /dev/null
+++ b/misc/tst-syscalls.c
@@ -0,0 +1,146 @@
+/* Test for syscall interfaces.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <support/check.h>
+#include <support/xunistd.h>
+
+struct Array
+{
+  size_t length;
+  void *ptr;
+};
+
+static int error_count;
+
+__attribute__ ((noclone, noinline))
+struct Array
+allocate (size_t bytes)
+{
+  if (!bytes)
+    return __extension__ (struct Array) {0, 0};
+
+  void *p = mmap (0x0, bytes, PROT_READ | PROT_WRITE,
+		  MAP_PRIVATE | MAP_ANON, -1, 0);
+  if (p == MAP_FAILED)
+    return __extension__ (struct Array) {0, 0};
+
+  return __extension__ (struct Array) {bytes, p};
+}
+
+__attribute__ ((noclone, noinline))
+void
+deallocate (struct Array b)
+{
+  if (b.length && munmap (b.ptr, b.length))
+    {
+      printf ("munmap error: %m\n");
+      error_count++;
+    }
+}
+
+__attribute__ ((noclone, noinline))
+void *
+do_mmap (void *addr, size_t length)
+{
+  return mmap (addr, length, PROT_READ | PROT_WRITE,
+	       MAP_PRIVATE | MAP_ANON, -1, 0);
+}
+
+__attribute__ ((noclone, noinline))
+void *
+reallocate (struct Array b)
+{
+  if (b.length)
+    return do_mmap (b.ptr, b.length);
+  return NULL;
+}
+
+__attribute__ ((noclone, noinline))
+void
+protect (struct Array b)
+{
+  if (b.length)
+    {
+      if (mprotect (b.ptr, b.length,
+		    PROT_READ | PROT_WRITE | PROT_EXEC))
+	{
+	  printf ("mprotect error: %m\n");
+	  error_count++;
+	}
+    }
+}
+
+__attribute__ ((noclone, noinline))
+ssize_t
+do_read (int fd, void *ptr, struct Array b)
+{
+  if (b.length)
+    return read (fd, ptr, b.length);
+  return 0;
+}
+
+__attribute__ ((noclone, noinline))
+ssize_t
+do_write (int fd, void *ptr, struct Array b)
+{
+  if (b.length)
+    return write (fd, ptr, b.length);
+  return 0;
+}
+
+static int
+do_test (void)
+{
+  struct Array array;
+
+  array = allocate (1);
+  protect (array);
+  deallocate (array);
+  void *p = reallocate (array);
+  if (p == MAP_FAILED)
+    {
+      printf ("mmap error: %m\n");
+      error_count++;
+    }
+  array.ptr = p;
+  protect (array);
+  deallocate (array);
+
+  int fd = xopen ("/dev/null", O_RDWR, 0);
+  char buf[2];
+  array.ptr = buf;
+  if (do_read (fd, array.ptr, array) == -1)
+    {
+      printf ("read error: %m\n");
+      error_count++;
+    }
+  if (do_write (fd, array.ptr, array) == -1)
+    {
+      printf ("write error: %m\n");
+      error_count++;
+    }
+  xclose (fd);
+
+  return error_count ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/unix/make-syscalls.sh b/sysdeps/unix/make-syscalls.sh
index c07626677f..52cf7e2f16 100644
--- a/sysdeps/unix/make-syscalls.sh
+++ b/sysdeps/unix/make-syscalls.sh
@@ -30,6 +30,7 @@
 # P: optionally-NULL pointer to typed object (e.g., 3rd argument to sigaction)
 # s: non-NULL string (e.g., 1st arg to open)
 # S: optionally-NULL string (e.g., 1st arg to acct)
+# U: unsigned long
 # v: vararg scalar (e.g., optional 3rd arg to open)
 # V: byte-per-page vector (3rd arg to mincore)
 # W: wait status, optionally-NULL pointer to int (e.g., 2nd arg of wait4)
@@ -184,6 +185,91 @@ while read file srcfile caller syscall args strong weak; do
   ?:?????????) nargs=9;;
   esac
 
+  # Derive the long arguments from the argument signature
+  ulong_arg_1=0
+  ulong_arg_2=0
+  case $args in
+  ?:U*)
+    ulong_arg_1=1
+    case $args in
+    ?:UU*) ulong_arg_2=2;;
+    ?:U?U*) ulong_arg_2=3;;
+    ?:U??U*) ulong_arg_2=4;;
+    ?:U???U*) ulong_arg_2=5;;
+    ?:U????U*) ulong_arg_2=6;;
+    ?:U?????U*) ulong_arg_2=7;;
+    ?:U??????U*) ulong_arg_2=8;;
+    ?:U???????U) ulong_arg_2=9;;
+    esac
+    ;;
+  ?:?U*)
+    ulong_arg_1=2
+    case $args in
+    ?:?UU*) ulong_arg_2=3;;
+    ?:?U?U*) ulong_arg_2=4;;
+    ?:?U??U*) ulong_arg_2=5;;
+    ?:?U???U*) ulong_arg_2=6;;
+    ?:?U????U*) ulong_arg_2=7;;
+    ?:?U?????U*) ulong_arg_2=8;;
+    ?:?U??????U) ulong_arg_2=9;;
+    esac
+    ;;
+  ?:??U*)
+    ulong_arg_1=3
+    case $args in
+    ?:??UU*) ulong_arg_2=4;;
+    ?:??U?U*) ulong_arg_2=5;;
+    ?:??U??U*) ulong_arg_2=6;;
+    ?:??U???U*) ulong_arg_2=7;;
+    ?:??U????U*) ulong_arg_2=8;;
+    ?:??U?????U) ulong_arg_2=9;;
+    esac
+    ;;
+  ?:???U*)
+    ulong_arg_1=4
+    case $args in
+    ?:???UU*) ulong_arg_2=5;;
+    ?:???U?U*) ulong_arg_2=6;;
+    ?:???U??U*) ulong_arg_2=7;;
+    ?:???U???U*) ulong_arg_2=8;;
+    ?:???U????U) ulong_arg_2=9;;
+    esac
+    ;;
+  ?:????U*)
+    ulong_arg_1=5
+    case $args in
+    ?:????UU*) ulong_arg_2=6;;
+    ?:????U?U*) ulong_arg_2=7;;
+    ?:????U??U*) ulong_arg_2=8;;
+    ?:????U???U) ulong_arg_2=9;;
+    esac
+    ;;
+  ?:?????U*)
+    ulong_arg_1=6
+    case $args in
+    ?:?????UU*) ulong_arg_2=7;;
+    ?:?????U?U*) ulong_arg_2=8;;
+    ?:?????U??U) ulong_arg_2=9;;
+    esac
+    ;;
+  ?:??????U*)
+    ulong_arg_1=7
+    case $args in
+    ?:??????UU*) ulong_arg_2=8;;
+    ?:??????U?U) ulong_arg_2=9;;
+    esac
+    ;;
+  ?:???????U*)
+    ulong_arg_1=8
+    case $args in
+    ?:??????UU) ulong_arg_2=9;;
+    esac
+    ;;
+  ?:????????U)
+    ulong_arg_1=9
+    ;;
+  esac
+
   # Make sure only the first syscall rule is used, if multiple dirs
   # define the same syscall.
   echo ''
@@ -245,6 +331,8 @@ while read file srcfile caller syscall args strong weak; do
 	\$(make-target-directory)
 	(echo '#define SYSCALL_NAME $syscall'; \\
 	 echo '#define SYSCALL_NARGS $nargs'; \\
+	 echo '#define SYSCALL_ULONG_ARG_1 $ulong_arg_1'; \\
+	 echo '#define SYSCALL_ULONG_ARG_2 $ulong_arg_2'; \\
 	 echo '#define SYSCALL_SYMBOL $strong'; \\
 	 echo '#define SYSCALL_NOERRNO $noerrno'; \\
 	 echo '#define SYSCALL_ERRVAL $errval'; \\
diff --git a/sysdeps/unix/syscall-template.S b/sysdeps/unix/syscall-template.S
index cf6c7a58fb..e8d6d59b15 100644
--- a/sysdeps/unix/syscall-template.S
+++ b/sysdeps/unix/syscall-template.S
@@ -25,6 +25,10 @@
    defining a few macros:
 	SYSCALL_NAME		syscall name
 	SYSCALL_NARGS		number of arguments this call takes
+	SYSCALL_ULONG_ARG_1	the first unsigned long argument this
+				call takes
+	SYSCALL_ULONG_ARG_2	the second unsigned long argument this
+				call takes
 	SYSCALL_SYMBOL		primary symbol name
 	SYSCALL_NOERRNO		1 to define a no-errno version (see below)
 	SYSCALL_ERRVAL		1 to define an error-value version (see below)
@@ -44,9 +48,21 @@
 /* This indirection is needed so that SYMBOL gets macro-expanded.  */
 #define syscall_hidden_def(SYMBOL)		hidden_def (SYMBOL)
 
-#define T_PSEUDO(SYMBOL, NAME, N)		PSEUDO (SYMBOL, NAME, N)
-#define T_PSEUDO_NOERRNO(SYMBOL, NAME, N)	PSEUDO_NOERRNO (SYMBOL, NAME, N)
-#define T_PSEUDO_ERRVAL(SYMBOL, NAME, N)	PSEUDO_ERRVAL (SYMBOL, NAME, N)
+#if SYSCALL_ULONG_ARG_1
+# define T_PSEUDO(SYMBOL, NAME, N, U1, U2) \
+  PSEUDO (SYMBOL, NAME, N, U1, U2)
+# define T_PSEUDO_NOERRNO(SYMBOL, NAME, N, U1, U2) \
+  PSEUDO_NOERRNO (SYMBOL, NAME, N, U1, U2)
+# define T_PSEUDO_ERRVAL(SYMBOL, NAME, N, U1, U2) \
+  PSEUDO_ERRVAL (SYMBOL, NAME, N, U1, U2)
+#else
+# define T_PSEUDO(SYMBOL, NAME, N) \
+  PSEUDO (SYMBOL, NAME, N)
+# define T_PSEUDO_NOERRNO(SYMBOL, NAME, N) \
+  PSEUDO_NOERRNO (SYMBOL, NAME, N)
+# define T_PSEUDO_ERRVAL(SYMBOL, NAME, N) \
+  PSEUDO_ERRVAL (SYMBOL, NAME, N)
+#endif
 #define T_PSEUDO_END(SYMBOL)			PSEUDO_END (SYMBOL)
 #define T_PSEUDO_END_NOERRNO(SYMBOL)		PSEUDO_END_NOERRNO (SYMBOL)
 #define T_PSEUDO_END_ERRVAL(SYMBOL)		PSEUDO_END_ERRVAL (SYMBOL)
@@ -56,7 +72,12 @@
 /* This kind of system call stub never returns an error.
    We return the return value register to the caller unexamined.  */
 
+# if SYSCALL_ULONG_ARG_1
+T_PSEUDO_NOERRNO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS,
+		  SYSCALL_ULONG_ARG_1, SYSCALL_ULONG_ARG_2)
+# else
 T_PSEUDO_NOERRNO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
+# endif
 	ret_NOERRNO
 T_PSEUDO_END_NOERRNO (SYSCALL_SYMBOL)
 
@@ -66,7 +87,12 @@ T_PSEUDO_END_NOERRNO (SYSCALL_SYMBOL)
    value, or zero for success.  We may massage the kernel's return value
    to meet that ABI, but we never set errno here.  */
 
+# if SYSCALL_ULONG_ARG_1
+T_PSEUDO_ERRVAL (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS,
+		 SYSCALL_ULONG_ARG_1, SYSCALL_ULONG_ARG_2)
+# else
 T_PSEUDO_ERRVAL (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
+# endif
 	ret_ERRVAL
 T_PSEUDO_END_ERRVAL (SYSCALL_SYMBOL)
 
@@ -75,7 +101,12 @@ T_PSEUDO_END_ERRVAL (SYSCALL_SYMBOL)
 /* This is a "normal" system call stub: if there is an error,
    it returns -1 and sets errno.  */
 
+# if SYSCALL_ULONG_ARG_1
+T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS,
+	  SYSCALL_ULONG_ARG_1, SYSCALL_ULONG_ARG_2)
+# else
 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
+# endif
 	ret
 T_PSEUDO_END (SYSCALL_SYMBOL)
 
diff --git a/sysdeps/unix/sysv/linux/copy_file_range.c b/sysdeps/unix/sysv/linux/copy_file_range.c
index a73c89f079..50487df77c 100644
--- a/sysdeps/unix/sysv/linux/copy_file_range.c
+++ b/sysdeps/unix/sysv/linux/copy_file_range.c
@@ -26,5 +26,5 @@ copy_file_range (int infd, __off64_t *pinoff,
                  size_t length, unsigned int flags)
 {
   return SYSCALL_CANCEL (copy_file_range, infd, pinoff, outfd, poutoff,
-                         length, flags);
+                         SYSCALL_ULONG (length), flags);
 }
diff --git a/sysdeps/unix/sysv/linux/getcwd.c b/sysdeps/unix/sysv/linux/getcwd.c
index fabc4bb8cc..d228467edf 100644
--- a/sysdeps/unix/sysv/linux/getcwd.c
+++ b/sysdeps/unix/sysv/linux/getcwd.c
@@ -75,7 +75,7 @@ __getcwd (char *buf, size_t size)
 
   int retval;
 
-  retval = INLINE_SYSCALL (getcwd, 2, path, alloc_size);
+  retval = INLINE_SYSCALL (getcwd, 2, path, SYSCALL_ULONG (alloc_size));
   if (retval > 0 && path[0] == '/')
     {
 #ifndef NO_ALLOCATION
diff --git a/sysdeps/unix/sysv/linux/getdents.c b/sysdeps/unix/sysv/linux/getdents.c
index a76be2e5e7..fc8da0caae 100644
--- a/sysdeps/unix/sysv/linux/getdents.c
+++ b/sysdeps/unix/sysv/linux/getdents.c
@@ -53,7 +53,8 @@ __getdents (int fd, void *buf0, size_t nbytes)
   if (nbytes <= sizeof (struct dirent))
     kbuf = (void*) kbuftmp;
 
-  retval = INLINE_SYSCALL_CALL (getdents64, fd, kbuf, kbytes);
+  retval = INLINE_SYSCALL_CALL (getdents64, fd, kbuf,
+				SYSCALL_ULONG (kbytes));
   if (retval == -1)
     return -1;
 
diff --git a/sysdeps/unix/sysv/linux/getdents64.c b/sysdeps/unix/sysv/linux/getdents64.c
index 75892c2823..63c89c7d60 100644
--- a/sysdeps/unix/sysv/linux/getdents64.c
+++ b/sysdeps/unix/sysv/linux/getdents64.c
@@ -29,7 +29,8 @@ __getdents64 (int fd, void *buf, size_t nbytes)
      checks in the kernel use an int type.  */
   if (nbytes > INT_MAX)
     nbytes = INT_MAX;
-  return INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes);
+  return INLINE_SYSCALL_CALL (getdents64, fd, buf,
+			      SYSCALL_ULONG (nbytes));
 }
 libc_hidden_def (__getdents64)
 weak_alias (__getdents64, getdents64)
@@ -74,7 +75,8 @@ __old_getdents64 (int fd, char *buf, size_t nbytes)
 		  <= __alignof__ (struct dirent64),
 		  "alignment of __old_dirent64 is larger than dirent64");
 
-  ssize_t retval = INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes);
+  ssize_t retval = INLINE_SYSCALL_CALL (getdents64, fd, buf,
+					SYSCALL_ULONG (nbytes));
   if (retval > 0)
     {
       /* This is the marker for the first entry.  Offset 0 is reserved
diff --git a/sysdeps/unix/sysv/linux/getentropy.c b/sysdeps/unix/sysv/linux/getentropy.c
index 2f3a4e4692..f99d2783a1 100644
--- a/sysdeps/unix/sysv/linux/getentropy.c
+++ b/sysdeps/unix/sysv/linux/getentropy.c
@@ -41,7 +41,9 @@ getentropy (void *buffer, size_t length)
   while (buffer < end)
     {
       /* NB: No cancellation point.  */
-      ssize_t bytes = INLINE_SYSCALL_CALL (getrandom, buffer, end - buffer, 0);
+      ssize_t bytes = INLINE_SYSCALL_CALL (getrandom, buffer,
+					   SYSCALL_ULONG (end - buffer),
+					   0);
       if (bytes < 0)
         {
           if (errno == EINTR)
diff --git a/sysdeps/unix/sysv/linux/getrandom.c b/sysdeps/unix/sysv/linux/getrandom.c
index 63b8d36bf4..8008890939 100644
--- a/sysdeps/unix/sysv/linux/getrandom.c
+++ b/sysdeps/unix/sysv/linux/getrandom.c
@@ -26,7 +26,8 @@
 ssize_t
 __getrandom (void *buffer, size_t length, unsigned int flags)
 {
-  return SYSCALL_CANCEL (getrandom, buffer, length, flags);
+  return SYSCALL_CANCEL (getrandom, buffer, SYSCALL_ULONG (length),
+			 flags);
 }
 libc_hidden_def (__getrandom)
 weak_alias (__getrandom, getrandom)
diff --git a/sysdeps/unix/sysv/linux/mlock2.c b/sysdeps/unix/sysv/linux/mlock2.c
index e52f43f35c..599ed5c351 100644
--- a/sysdeps/unix/sysv/linux/mlock2.c
+++ b/sysdeps/unix/sysv/linux/mlock2.c
@@ -23,11 +23,13 @@ int
 mlock2 (const void *addr, size_t length, unsigned int flags)
 {
 #ifdef __ASSUME_MLOCK2
-  return INLINE_SYSCALL_CALL (mlock2, addr, length, flags);
+  return INLINE_SYSCALL_CALL (mlock2, addr, SYSCALL_ULONG (length),
+			      flags);
 #else
   if (flags == 0)
-    return INLINE_SYSCALL_CALL (mlock, addr, length);
-  int ret = INLINE_SYSCALL_CALL (mlock2, addr, length, flags);
+    return INLINE_SYSCALL_CALL (mlock, addr, SYSCALL_ULONG (length));
+  int ret = INLINE_SYSCALL_CALL (mlock2, addr, SYSCALL_ULONG (length),
+				 flags);
   if (ret == 0 || errno != ENOSYS)
     return ret;
   /* Treat the missing system call as an invalid (non-zero) flag
diff --git a/sysdeps/unix/sysv/linux/mmap64.c b/sysdeps/unix/sysv/linux/mmap64.c
index 8074deb466..7efe7f171d 100644
--- a/sysdeps/unix/sysv/linux/mmap64.c
+++ b/sysdeps/unix/sysv/linux/mmap64.c
@@ -53,10 +53,11 @@ __mmap64 (void *addr, size_t len, int prot, int flags, int fd, off64_t offset)
 
   MMAP_PREPARE (addr, len, prot, flags, fd, offset);
 #ifdef __NR_mmap2
-  return (void *) MMAP_CALL (mmap2, addr, len, prot, flags, fd,
-			     (off_t) (offset / MMAP2_PAGE_UNIT));
+  return (void *) MMAP_CALL (mmap2, addr, SYSCALL_ULONG (len), prot, flags,
+			     fd, (off_t) (offset / MMAP2_PAGE_UNIT));
 #else
-  return (void *) MMAP_CALL (mmap, addr, len, prot, flags, fd, offset);
+  return (void *) MMAP_CALL (mmap, addr, SYSCALL_ULONG (len), prot, flags,
+			     fd, offset);
 #endif
 }
 weak_alias (__mmap64, mmap64)
diff --git a/sysdeps/unix/sysv/linux/mq_timedreceive.c b/sysdeps/unix/sysv/linux/mq_timedreceive.c
index 728a63d1ec..aae1443196 100644
--- a/sysdeps/unix/sysv/linux/mq_timedreceive.c
+++ b/sysdeps/unix/sysv/linux/mq_timedreceive.c
@@ -30,11 +30,12 @@ __mq_timedreceive_time64 (mqd_t mqdes, char *__restrict msg_ptr, size_t msg_len,
 # ifndef __NR_mq_timedreceive_time64
 #  define __NR_mq_timedreceive_time64 __NR_mq_timedreceive
 # endif
-  return SYSCALL_CANCEL (mq_timedreceive_time64, mqdes, msg_ptr, msg_len,
-                         msg_prio, abs_timeout);
+  return SYSCALL_CANCEL (mq_timedreceive_time64, mqdes, msg_ptr,
+			 SYSCALL_ULONG (msg_len), msg_prio, abs_timeout);
 #else
-  int ret = SYSCALL_CANCEL (mq_timedreceive_time64, mqdes, msg_ptr, msg_len,
-                            msg_prio, abs_timeout);
+  int ret = SYSCALL_CANCEL (mq_timedreceive_time64, mqdes, msg_ptr,
+			    SYSCALL_ULONG (msg_len), msg_prio,
+			    abs_timeout);
   if (ret == 0 || errno != ENOSYS)
     return ret;
 
@@ -50,7 +51,8 @@ __mq_timedreceive_time64 (mqd_t mqdes, char *__restrict msg_ptr, size_t msg_len,
       ts32 = valid_timespec64_to_timespec (*abs_timeout);
     }
 
-  return SYSCALL_CANCEL (mq_timedreceive, mqdes, msg_ptr, msg_len, msg_prio,
+  return SYSCALL_CANCEL (mq_timedreceive, mqdes, msg_ptr,
+			 SYSCALL_ULONG (msg_len), msg_prio,
                          abs_timeout != NULL ? &ts32 : NULL);
 #endif
 }
diff --git a/sysdeps/unix/sysv/linux/mq_timedsend.c b/sysdeps/unix/sysv/linux/mq_timedsend.c
index f2a43df300..7e174df888 100644
--- a/sysdeps/unix/sysv/linux/mq_timedsend.c
+++ b/sysdeps/unix/sysv/linux/mq_timedsend.c
@@ -30,11 +30,11 @@ __mq_timedsend_time64 (mqd_t mqdes, const char *msg_ptr, size_t msg_len,
 # ifndef __NR_mq_timedsend_time64
 #  define __NR_mq_timedsend_time64 __NR_mq_timedsend
 # endif
-  return SYSCALL_CANCEL (mq_timedsend_time64, mqdes, msg_ptr, msg_len,
-                         msg_prio, abs_timeout);
+  return SYSCALL_CANCEL (mq_timedsend_time64, mqdes, msg_ptr,
+			 SYSCALL_ULONG (msg_len), msg_prio, abs_timeout);
 #else
-  int ret = SYSCALL_CANCEL (mq_timedsend_time64, mqdes, msg_ptr, msg_len,
-                            msg_prio, abs_timeout);
+  int ret = SYSCALL_CANCEL (mq_timedsend_time64, mqdes, msg_ptr,
+			    SYSCALL_ULONG (msg_len), msg_prio, abs_timeout);
   if (ret == 0 || errno != ENOSYS)
     return ret;
 
@@ -50,7 +50,8 @@ __mq_timedsend_time64 (mqd_t mqdes, const char *msg_ptr, size_t msg_len,
       ts32 = valid_timespec64_to_timespec (*abs_timeout);
     }
 
-  return SYSCALL_CANCEL (mq_timedsend, mqdes, msg_ptr, msg_len, msg_prio,
+  return SYSCALL_CANCEL (mq_timedsend, mqdes, msg_ptr,
+			 SYSCALL_ULONG (msg_len), msg_prio,
                          abs_timeout != NULL ? &ts32 : NULL);
 #endif
 }
@@ -66,7 +67,8 @@ __mq_timedsend (mqd_t mqdes, const char *msg_ptr, size_t msg_len,
   if (abs_timeout != NULL)
     ts64 = valid_timespec_to_timespec64 (*abs_timeout);
 
-  return __mq_timedsend_time64 (mqdes, msg_ptr, msg_len, msg_prio,
+  return __mq_timedsend_time64 (mqdes, msg_ptr,
+				SYSCALL_ULONG (msg_len), msg_prio,
                                 abs_timeout != NULL ? &ts64 : NULL);
 }
 #endif
diff --git a/sysdeps/unix/sysv/linux/msgrcv.c b/sysdeps/unix/sysv/linux/msgrcv.c
index 95edc7a787..ecfa2df4fb 100644
--- a/sysdeps/unix/sysv/linux/msgrcv.c
+++ b/sysdeps/unix/sysv/linux/msgrcv.c
@@ -25,10 +25,11 @@ __libc_msgrcv (int msqid, void *msgp, size_t msgsz, long int msgtyp,
 	       int msgflg)
 {
 #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
-  return SYSCALL_CANCEL (msgrcv, msqid, msgp, msgsz, msgtyp, msgflg);
+  return SYSCALL_CANCEL (msgrcv, msqid, msgp, SYSCALL_ULONG (msgsz),
+			 SYSCALL_LONG (msgtyp), msgflg);
 #else
-  return SYSCALL_CANCEL (ipc, IPCOP_msgrcv, msqid, msgsz, msgflg,
-			 MSGRCV_ARGS (msgp, msgtyp));
+  return SYSCALL_CANCEL (ipc, IPCOP_msgrcv, msqid, SYSCALL_ULONG (msgsz),
+			 msgflg, MSGRCV_ARGS (msgp, SYSCALL_LONG (msgtyp)));
 #endif
 }
 weak_alias (__libc_msgrcv, msgrcv)
diff --git a/sysdeps/unix/sysv/linux/msgsnd.c b/sysdeps/unix/sysv/linux/msgsnd.c
index 554516f2ca..9e329d8e72 100644
--- a/sysdeps/unix/sysv/linux/msgsnd.c
+++ b/sysdeps/unix/sysv/linux/msgsnd.c
@@ -24,10 +24,11 @@ int
 __libc_msgsnd (int msqid, const void *msgp, size_t msgsz, int msgflg)
 {
 #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
-  return SYSCALL_CANCEL (msgsnd, msqid, msgp, msgsz, msgflg);
+  return SYSCALL_CANCEL (msgsnd, msqid, msgp, SYSCALL_ULONG (msgsz),
+			 msgflg);
 #else
-  return SYSCALL_CANCEL (ipc, IPCOP_msgsnd, msqid, msgsz, msgflg,
-			 msgp);
+  return SYSCALL_CANCEL (ipc, IPCOP_msgsnd, msqid, SYSCALL_ULONG (msgsz),
+			 msgflg, msgp);
 #endif
 }
 weak_alias (__libc_msgsnd, msgsnd)
diff --git a/sysdeps/unix/sysv/linux/msync.c b/sysdeps/unix/sysv/linux/msync.c
index de1dd2ac5e..0ef48a1eaf 100644
--- a/sysdeps/unix/sysv/linux/msync.c
+++ b/sysdeps/unix/sysv/linux/msync.c
@@ -22,5 +22,5 @@
 int
 msync (void *addr, size_t length, int flags)
 {
-  return SYSCALL_CANCEL (msync, addr, length, flags);
+  return SYSCALL_CANCEL (msync, addr, SYSCALL_ULONG (length), flags);
 }
diff --git a/sysdeps/unix/sysv/linux/pkey_mprotect.c b/sysdeps/unix/sysv/linux/pkey_mprotect.c
index 4ec1feba2e..9130bbdef6 100644
--- a/sysdeps/unix/sysv/linux/pkey_mprotect.c
+++ b/sysdeps/unix/sysv/linux/pkey_mprotect.c
@@ -28,5 +28,6 @@ pkey_mprotect (void *addr, size_t len, int prot, int pkey)
     /* If the key is -1, the system call is precisely equivalent to
        mprotect.  */
     return __mprotect (addr, len, prot);
-  return INLINE_SYSCALL_CALL (pkey_mprotect, addr, len, prot, pkey);
+  return INLINE_SYSCALL_CALL (pkey_mprotect, addr, SYSCALL_ULONG (len),
+			      prot, pkey);
 }
diff --git a/sysdeps/unix/sysv/linux/pread.c b/sysdeps/unix/sysv/linux/pread.c
index 8dd87b3976..41d51d810c 100644
--- a/sysdeps/unix/sysv/linux/pread.c
+++ b/sysdeps/unix/sysv/linux/pread.c
@@ -24,7 +24,8 @@
 ssize_t
 __libc_pread (int fd, void *buf, size_t count, off_t offset)
 {
-  return SYSCALL_CANCEL (pread64, fd, buf, count, SYSCALL_LL_PRW (offset));
+  return SYSCALL_CANCEL (pread64, fd, buf, SYSCALL_ULONG (count),
+			 SYSCALL_LL_PRW (offset));
 }
 
 strong_alias (__libc_pread, __pread)
diff --git a/sysdeps/unix/sysv/linux/pread64.c b/sysdeps/unix/sysv/linux/pread64.c
index 3d4ffbafc1..7a7bf7076c 100644
--- a/sysdeps/unix/sysv/linux/pread64.c
+++ b/sysdeps/unix/sysv/linux/pread64.c
@@ -22,7 +22,8 @@
 ssize_t
 __libc_pread64 (int fd, void *buf, size_t count, off64_t offset)
 {
-  return SYSCALL_CANCEL (pread64, fd, buf, count, SYSCALL_LL64_PRW (offset));
+  return SYSCALL_CANCEL (pread64, fd, buf, SYSCALL_ULONG (count),
+			 SYSCALL_LL64_PRW (offset));
 }
 
 weak_alias (__libc_pread64, __pread64)
diff --git a/sysdeps/unix/sysv/linux/pread64_nocancel.c b/sysdeps/unix/sysv/linux/pread64_nocancel.c
index af33985959..ea9e3be552 100644
--- a/sysdeps/unix/sysv/linux/pread64_nocancel.c
+++ b/sysdeps/unix/sysv/linux/pread64_nocancel.c
@@ -23,6 +23,7 @@
 ssize_t
 __pread64_nocancel (int fd, void *buf, size_t count, off64_t offset)
 {
-  return INLINE_SYSCALL_CALL (pread64, fd, buf, count, SYSCALL_LL64_PRW (offset));
+  return INLINE_SYSCALL_CALL (pread64, fd, buf, SYSCALL_ULONG (count),
+			      SYSCALL_LL64_PRW (offset));
 }
 hidden_def (__pread64_nocancel)
diff --git a/sysdeps/unix/sysv/linux/pwrite.c b/sysdeps/unix/sysv/linux/pwrite.c
index 17964686e5..c1cddbfe81 100644
--- a/sysdeps/unix/sysv/linux/pwrite.c
+++ b/sysdeps/unix/sysv/linux/pwrite.c
@@ -24,7 +24,8 @@
 ssize_t
 __libc_pwrite (int fd, const void *buf, size_t count, off_t offset)
 {
-  return SYSCALL_CANCEL (pwrite64, fd, buf, count, SYSCALL_LL_PRW (offset));
+  return SYSCALL_CANCEL (pwrite64, fd, buf, SYSCALL_ULONG (count),
+			 SYSCALL_LL_PRW (offset));
 }
 
 strong_alias (__libc_pwrite, __pwrite)
diff --git a/sysdeps/unix/sysv/linux/pwrite64.c b/sysdeps/unix/sysv/linux/pwrite64.c
index 709775c207..a47c309144 100644
--- a/sysdeps/unix/sysv/linux/pwrite64.c
+++ b/sysdeps/unix/sysv/linux/pwrite64.c
@@ -22,7 +22,8 @@
 ssize_t
 __libc_pwrite64 (int fd, const void *buf, size_t count, off64_t offset)
 {
-  return SYSCALL_CANCEL (pwrite64, fd, buf, count, SYSCALL_LL64_PRW (offset));
+  return SYSCALL_CANCEL (pwrite64, fd, buf, SYSCALL_ULONG (count),
+			 SYSCALL_LL64_PRW (offset));
 }
 
 weak_alias (__libc_pwrite64, __pwrite64)
diff --git a/sysdeps/unix/sysv/linux/read.c b/sysdeps/unix/sysv/linux/read.c
index 64f558a587..6c37b4fba9 100644
--- a/sysdeps/unix/sysv/linux/read.c
+++ b/sysdeps/unix/sysv/linux/read.c
@@ -23,7 +23,7 @@
 ssize_t
 __libc_read (int fd, void *buf, size_t nbytes)
 {
-  return SYSCALL_CANCEL (read, fd, buf, nbytes);
+  return SYSCALL_CANCEL (read, fd, buf, SYSCALL_ULONG (nbytes));
 }
 libc_hidden_def (__libc_read)
 
diff --git a/sysdeps/unix/sysv/linux/read_nocancel.c b/sysdeps/unix/sysv/linux/read_nocancel.c
index f9d8a3b563..4a734e9d83 100644
--- a/sysdeps/unix/sysv/linux/read_nocancel.c
+++ b/sysdeps/unix/sysv/linux/read_nocancel.c
@@ -23,6 +23,6 @@
 ssize_t
 __read_nocancel (int fd, void *buf, size_t nbytes)
 {
-  return INLINE_SYSCALL_CALL (read, fd, buf, nbytes);
+  return INLINE_SYSCALL_CALL (read, fd, buf, SYSCALL_ULONG (nbytes));
 }
 hidden_def (__read_nocancel)
diff --git a/sysdeps/unix/sysv/linux/readahead.c b/sysdeps/unix/sysv/linux/readahead.c
index a189c3ac79..46a98c000a 100644
--- a/sysdeps/unix/sysv/linux/readahead.c
+++ b/sysdeps/unix/sysv/linux/readahead.c
@@ -25,6 +25,6 @@ __readahead (int fd, off64_t offset, size_t count)
 {
   return INLINE_SYSCALL_CALL (readahead, fd,
 			      __ALIGNMENT_ARG SYSCALL_LL64 (offset),
-			      count);
+			      SYSCALL_ULONG (count));
 }
 weak_alias (__readahead, readahead)
diff --git a/sysdeps/unix/sysv/linux/recv.c b/sysdeps/unix/sysv/linux/recv.c
index 79fb3c32d1..9ab079cc7c 100644
--- a/sysdeps/unix/sysv/linux/recv.c
+++ b/sysdeps/unix/sysv/linux/recv.c
@@ -23,11 +23,12 @@ ssize_t
 __libc_recv (int fd, void *buf, size_t len, int flags)
 {
 #ifdef __ASSUME_RECV_SYSCALL
-  return SYSCALL_CANCEL (recv, fd, buf, len, flags);
+  return SYSCALL_CANCEL (recv, fd, buf, SYSCALL_ULONG (len), flags);
 #elif defined __ASSUME_RECVFROM_SYSCALL
-  return SYSCALL_CANCEL (recvfrom, fd, buf, len, flags, NULL, NULL);
+  return SYSCALL_CANCEL (recvfrom, fd, buf, SYSCALL_ULONG (len), flags,
+			 NULL, NULL);
 #else
-  return SOCKETCALL_CANCEL (recv, fd, buf, len, flags);
+  return SOCKETCALL_CANCEL (recv, fd, buf, SYSCALL_ULONG (len), flags);
 #endif
 }
 weak_alias (__libc_recv, recv)
diff --git a/sysdeps/unix/sysv/linux/recvfrom.c b/sysdeps/unix/sysv/linux/recvfrom.c
index 70532529c9..caf3b66738 100644
--- a/sysdeps/unix/sysv/linux/recvfrom.c
+++ b/sysdeps/unix/sysv/linux/recvfrom.c
@@ -24,11 +24,11 @@ __libc_recvfrom (int fd, void *buf, size_t len, int flags,
 		 __SOCKADDR_ARG addr, socklen_t *addrlen)
 {
 #ifdef __ASSUME_RECVFROM_SYSCALL
-  return SYSCALL_CANCEL (recvfrom, fd, buf, len, flags, addr.__sockaddr__,
-                         addrlen);
+  return SYSCALL_CANCEL (recvfrom, fd, buf, SYSCALL_ULONG (len), flags,
+			 addr.__sockaddr__, addrlen);
 #else
-  return SOCKETCALL_CANCEL (recvfrom, fd, buf, len, flags, addr.__sockaddr__,
-			    addrlen);
+  return SOCKETCALL_CANCEL (recvfrom, fd, buf, SYSCALL_ULONG (len),
+			    flags, addr.__sockaddr__, addrlen);
 #endif
 }
 weak_alias (__libc_recvfrom, recvfrom)
diff --git a/sysdeps/unix/sysv/linux/sched_setaffinity.c b/sysdeps/unix/sysv/linux/sched_setaffinity.c
index fc2c692783..aea179464c 100644
--- a/sysdeps/unix/sysv/linux/sched_setaffinity.c
+++ b/sysdeps/unix/sysv/linux/sched_setaffinity.c
@@ -30,7 +30,8 @@ libc_hidden_proto (__sched_setaffinity_new)
 int
 __sched_setaffinity_new (pid_t pid, size_t cpusetsize, const cpu_set_t *cpuset)
 {
-  int result = INLINE_SYSCALL (sched_setaffinity, 3, pid, cpusetsize, cpuset);
+  int result = INLINE_SYSCALL (sched_setaffinity, 3, pid,
+			       SYSCALL_ULONG (cpusetsize), cpuset);
 
 #ifdef RESET_VGETCPU_CACHE
   if (result != -1)
diff --git a/sysdeps/unix/sysv/linux/semtimedop.c b/sysdeps/unix/sysv/linux/semtimedop.c
index 6fdde09bad..f3b240ca9b 100644
--- a/sysdeps/unix/sysv/linux/semtimedop.c
+++ b/sysdeps/unix/sysv/linux/semtimedop.c
@@ -30,10 +30,12 @@ __semtimedop (int semid, struct sembuf *sops, size_t nsops,
   /* semtimedop wire-up syscall is not exported for 32-bit ABIs (they have
      semtimedop_time64 instead with uses a 64-bit time_t).  */
 #if defined __ASSUME_DIRECT_SYSVIPC_SYSCALLS && defined __NR_semtimedop
-  return INLINE_SYSCALL_CALL (semtimedop, semid, sops, nsops, timeout);
+  return INLINE_SYSCALL_CALL (semtimedop, semid, sops,
+			      SYSCALL_ULONG (nsops), timeout);
 #else
   return INLINE_SYSCALL_CALL (ipc, IPCOP_semtimedop, semid,
-			      SEMTIMEDOP_IPC_ARGS (nsops, sops, timeout));
+			      SEMTIMEDOP_IPC_ARGS (SYSCALL_ULONG (nsops),
+						   sops, timeout));
 #endif
 }
 weak_alias (__semtimedop, semtimedop)
diff --git a/sysdeps/unix/sysv/linux/send.c b/sysdeps/unix/sysv/linux/send.c
index aed7d06585..cd8725d05b 100644
--- a/sysdeps/unix/sysv/linux/send.c
+++ b/sysdeps/unix/sysv/linux/send.c
@@ -23,11 +23,12 @@ ssize_t
 __libc_send (int fd, const void *buf, size_t len, int flags)
 {
 #ifdef __ASSUME_SEND_SYSCALL
-  return SYSCALL_CANCEL (send, fd, buf, len, flags);
+  return SYSCALL_CANCEL (send, fd, buf, SYSCALL_ULONG (len), flags);
 #elif defined __ASSUME_SENDTO_SYSCALL
-  return SYSCALL_CANCEL (sendto, fd, buf, len, flags, NULL, 0);
+  return SYSCALL_CANCEL (sendto, fd, buf, SYSCALL_ULONG (len), flags,
+			 NULL, 0);
 #else
-  return SOCKETCALL_CANCEL (send, fd, buf, len, flags);
+  return SOCKETCALL_CANCEL (send, fd, buf, SYSCALL_ULONG (len), flags);
 #endif
 }
 weak_alias (__libc_send, send)
diff --git a/sysdeps/unix/sysv/linux/sendto.c b/sysdeps/unix/sysv/linux/sendto.c
index 670d0679ea..ceb61305af 100644
--- a/sysdeps/unix/sysv/linux/sendto.c
+++ b/sysdeps/unix/sysv/linux/sendto.c
@@ -24,11 +24,11 @@ __libc_sendto (int fd, const void *buf, size_t len, int flags,
 	       __CONST_SOCKADDR_ARG addr, socklen_t addrlen)
 {
 #ifdef __ASSUME_SENDTO_SYSCALL
-  return SYSCALL_CANCEL (sendto, fd, buf, len, flags, addr.__sockaddr__,
-                         addrlen);
+  return SYSCALL_CANCEL (sendto, fd, buf, SYSCALL_ULONG (len), flags,
+			 addr.__sockaddr__, addrlen);
 #else
-  return SOCKETCALL_CANCEL (sendto, fd, buf, len, flags, addr.__sockaddr__,
-			    addrlen);
+  return SOCKETCALL_CANCEL (sendto, fd, buf, SYSCALL_ULONG (len), flags,
+			    addr.__sockaddr__, addrlen);
 #endif
 }
 weak_alias (__libc_sendto, sendto)
diff --git a/sysdeps/unix/sysv/linux/shmget.c b/sysdeps/unix/sysv/linux/shmget.c
index 6f7ce8c057..1032142170 100644
--- a/sysdeps/unix/sysv/linux/shmget.c
+++ b/sysdeps/unix/sysv/linux/shmget.c
@@ -28,8 +28,10 @@ int
 shmget (key_t key, size_t size, int shmflg)
 {
 #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
-  return INLINE_SYSCALL_CALL (shmget, key, size, shmflg, NULL);
+  return INLINE_SYSCALL_CALL (shmget, key, SYSCALL_ULONG (size),
+			      shmflg, NULL);
 #else
-  return INLINE_SYSCALL_CALL (ipc, IPCOP_shmget, key, size, shmflg, NULL);
+  return INLINE_SYSCALL_CALL (ipc, IPCOP_shmget, key,
+			      SYSCALL_ULONG (size), shmflg, NULL);
 #endif
 }
diff --git a/sysdeps/unix/sysv/linux/splice.c b/sysdeps/unix/sysv/linux/splice.c
index fe21cf1988..199608fffa 100644
--- a/sysdeps/unix/sysv/linux/splice.c
+++ b/sysdeps/unix/sysv/linux/splice.c
@@ -23,5 +23,6 @@ ssize_t
 splice (int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len,
 	unsigned int flags)
 {
-  return SYSCALL_CANCEL (splice, fd_in, off_in, fd_out, off_out, len, flags);
+  return SYSCALL_CANCEL (splice, fd_in, off_in, fd_out, off_out,
+			 SYSCALL_ULONG (len), flags);
 }
diff --git a/sysdeps/unix/sysv/linux/sysdep.h b/sysdeps/unix/sysv/linux/sysdep.h
index 5e7b6c5765..0ab65e40a5 100644
--- a/sysdeps/unix/sysv/linux/sysdep.h
+++ b/sysdeps/unix/sysv/linux/sysdep.h
@@ -94,6 +94,11 @@
  (long) (val), \
  (long) (((uint64_t) (val)) >> 32)
 
+/* Provide common macros to pass long/unsigned long (ssize_t/size_t)
+   values on syscalls.  */
+#define SYSCALL_LONG(val) (val)
+#define SYSCALL_ULONG(val) (val)
+
 /* Exports the __send symbol on send.c linux implementation (some ABI have
    it missing due the usage of a old generic version without it).  */
 #define HAVE_INTERNAL_SEND_SYMBOL	1
diff --git a/sysdeps/unix/sysv/linux/tee.c b/sysdeps/unix/sysv/linux/tee.c
index 0e62c226dd..f404768ef6 100644
--- a/sysdeps/unix/sysv/linux/tee.c
+++ b/sysdeps/unix/sysv/linux/tee.c
@@ -22,5 +22,5 @@
 ssize_t
 tee (int src, int dest, size_t len, unsigned int flags)
 {
-  return SYSCALL_CANCEL (tee, src, dest, len, flags);
+  return SYSCALL_CANCEL (tee, src, dest, SYSCALL_ULONG (len), flags);
 }
diff --git a/sysdeps/unix/sysv/linux/vmsplice.c b/sysdeps/unix/sysv/linux/vmsplice.c
index 17cc7bf8e7..e338a73944 100644
--- a/sysdeps/unix/sysv/linux/vmsplice.c
+++ b/sysdeps/unix/sysv/linux/vmsplice.c
@@ -23,5 +23,5 @@
 ssize_t
 vmsplice (int fd, const struct iovec *iov, size_t count, unsigned int flags)
 {
-  return SYSCALL_CANCEL (vmsplice, fd, iov, count, flags);
+  return SYSCALL_CANCEL (vmsplice, fd, iov, SYSCALL_ULONG (count), flags);
 }
diff --git a/sysdeps/unix/sysv/linux/write.c b/sysdeps/unix/sysv/linux/write.c
index 7848f7de27..2176572425 100644
--- a/sysdeps/unix/sysv/linux/write.c
+++ b/sysdeps/unix/sysv/linux/write.c
@@ -23,7 +23,7 @@
 ssize_t
 __libc_write (int fd, const void *buf, size_t nbytes)
 {
-  return SYSCALL_CANCEL (write, fd, buf, nbytes);
+  return SYSCALL_CANCEL (write, fd, buf, SYSCALL_ULONG (nbytes));
 }
 libc_hidden_def (__libc_write)
 
diff --git a/sysdeps/unix/sysv/linux/write_nocancel.c b/sysdeps/unix/sysv/linux/write_nocancel.c
index 36d406cf74..17aa7d4797 100644
--- a/sysdeps/unix/sysv/linux/write_nocancel.c
+++ b/sysdeps/unix/sysv/linux/write_nocancel.c
@@ -23,6 +23,6 @@
 ssize_t
 __write_nocancel (int fd, const void *buf, size_t nbytes)
 {
-  return INLINE_SYSCALL_CALL (write, fd, buf, nbytes);
+  return INLINE_SYSCALL_CALL (write, fd, buf, SYSCALL_ULONG (nbytes));
 }
 hidden_def (__write_nocancel)
diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
index 24d8b8ec20..a8a8e95fa5 100644
--- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
@@ -57,13 +57,27 @@
 #  define SYSCALL_ERROR_LABEL syscall_error
 # endif
 
+# ifndef SYSCALL_ULONG_ARG_1
+#  define SYSCALL_ULONG_ARG_1 0
+#  define SYSCALL_ULONG_ARG_2 0
+# endif
+
 # undef	PSEUDO
-# define PSEUDO(name, syscall_name, args)				      \
-  .text;								      \
-  ENTRY (name)								      \
-    DO_CALL (syscall_name, args);					      \
-    cmpq $-4095, %rax;							      \
+# if SYSCALL_ULONG_ARG_1
+#  define PSEUDO(name, syscall_name, args, long_arg_1, long_arg_2) \
+  .text;							      \
+  ENTRY (name)							      \
+    DO_CALL (syscall_name, args, long_arg_1, long_arg_2);	      \
+    cmpq $-4095, %rax;						      \
     jae SYSCALL_ERROR_LABEL
+# else
+#  define PSEUDO(name, syscall_name, args) \
+  .text;							      \
+  ENTRY (name)							      \
+    DO_CALL (syscall_name, args, 0, 0);				      \
+    cmpq $-4095, %rax;						      \
+    jae SYSCALL_ERROR_LABEL
+# endif
 
 # undef	PSEUDO_END
 # define PSEUDO_END(name)						      \
@@ -71,10 +85,17 @@
   END (name)
 
 # undef	PSEUDO_NOERRNO
-# define PSEUDO_NOERRNO(name, syscall_name, args) \
-  .text;								      \
-  ENTRY (name)								      \
-    DO_CALL (syscall_name, args)
+# if SYSCALL_ULONG_ARG_1
+#  define PSEUDO_NOERRNO(name, syscall_name, args, long_arg_1, long_arg_2) \
+  .text;							      \
+  ENTRY (name)							      \
+    DO_CALL (syscall_name, args, long_arg_1, long_arg_2)
+# else
+#  define PSEUDO_NOERRNO(name, syscall_name, args) \
+  .text;							      \
+  ENTRY (name)							      \
+    DO_CALL (syscall_name, args, 0, 0)
+# endif
 
 # undef	PSEUDO_END_NOERRNO
 # define PSEUDO_END_NOERRNO(name) \
@@ -83,11 +104,19 @@
 # define ret_NOERRNO ret
 
 # undef	PSEUDO_ERRVAL
-# define PSEUDO_ERRVAL(name, syscall_name, args) \
-  .text;								      \
-  ENTRY (name)								      \
-    DO_CALL (syscall_name, args);					      \
+# if SYSCALL_ULONG_ARG_1
+#  define PSEUDO_ERRVAL(name, syscall_name, args, long_arg_1, long_arg_2) \
+  .text;							\
+  ENTRY (name)							\
+    DO_CALL (syscall_name, args, long_arg_1, long_arg_2);	\
     negq %rax
+# else
+#  define PSEUDO_ERRVAL(name, syscall_name, args) \
+  .text;							\
+  ENTRY (name)							\
+    DO_CALL (syscall_name, args, 0, 0);				\
+    negq %rax
+# endif
 
 # undef	PSEUDO_END_ERRVAL
 # define PSEUDO_END_ERRVAL(name) \
@@ -159,7 +188,7 @@
     Syscalls of more than 6 arguments are not supported.  */
 
 # undef	DO_CALL
-# define DO_CALL(syscall_name, args)		\
+# define DO_CALL(syscall_name, args, long_arg_1, long_arg_2) \
     DOARGS_##args				\
     movl $SYS_ify (syscall_name), %eax;		\
     syscall;
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/syscalls.list b/sysdeps/unix/sysv/linux/x86_64/x32/syscalls.list
index 58ea31d1fd..dfc551d402 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/syscalls.list
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/syscalls.list
@@ -1,4 +1,14 @@
 # File name	Caller	Syscall name	# args	Strong name	Weak names
 
+madvise		-	madvise		i:pUi	__madvise	madvise
+mincore		-	mincore		i:aUV	mincore
+mprotect	-	mprotect	i:aUi	__mprotect	mprotect
+mlock		-	mlock		i:bU	mlock
+mount		EXTRA	mount		i:sssUp	__mount	mount
+mremap		EXTRA	mremap		b:aUUip	__mremap	mremap
+munlock		-	munlock		i:aU	munlock
+munmap		-	munmap		i:aU	__munmap	munmap
 personality	EXTRA	personality	Ei:i	__personality	personality
 posix_fadvise64	-	fadvise64	Vi:iiii	posix_fadvise	posix_fadvise64
+remap_file_pages -	remap_file_pages i:pUiUi	__remap_file_pages remap_file_pages
+sendfile	-	sendfile	i:iipU	sendfile	sendfile64
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h
index 5bf9eed80b..d6898eb080 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h
@@ -26,4 +26,34 @@
 #undef LO_HI_LONG
 #define LO_HI_LONG(val) (val)
 
+/* How to pass  pass long/unsigned long (ssize_t/size_t) on syscalls. */
+#undef SYSCALL_LONG
+#define SYSCALL_LONG(val) ((int64_t) (val))
+#undef SYSCALL_ULONG
+#define SYSCALL_ULONG(val) ((uint64_t) (val))
+
+#ifdef __ASSEMBLER__
+# undef	DO_CALL
+# define DO_CALL(syscall_name, args, long_arg_1, long_arg_2)	\
+  DOARGS_##args							\
+  ZERO_EXTEND_##long_arg_1					\
+  ZERO_EXTEND_##long_arg_2					\
+  movl $SYS_ify (syscall_name), %eax;				\
+  syscall;
+
+# define ZERO_EXTEND_0 /* nothing */
+# define ZERO_EXTEND_1 movl %edi, %edi;
+# define ZERO_EXTEND_2 movl %esi, %esi;
+# define ZERO_EXTEND_3 movl %edx, %edx;
+# define ZERO_EXTEND_4 movl %r10d, %r10d;
+# define ZERO_EXTEND_5 movl %r8d, %r8d;
+# define ZERO_EXTEND_6 movl %r9d, %r9d;
+
+# if SYSCALL_ULONG_ARG_1 == 4 || SYSCALL_ULONG_ARG_2 == 4
+#  undef ZERO_EXTEND_4
+#  define ZERO_EXTEND_4 /* nothing */
+#  define DOARGS_4 movl %ecx, %r10d;
+# endif
+#endif	/* __ASSEMBLER__ */
+
 #endif /* linux/x86_64/x32/sysdep.h */
-- 
2.25.2



More information about the Libc-alpha mailing list