]> sourceware.org Git - glibc.git/commitdiff
Add SYSCALL_ULONG_ARG_[12] to pass long to syscall [BZ #25810]
authorH.J. Lu <hjl.tools@gmail.com>
Wed, 29 Apr 2020 12:35:34 +0000 (05:35 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 29 Apr 2020 12:35:34 +0000 (05:35 -0700)
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 int 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 syscalls implemented in assembly codes, 'U' is added to syscall
signature key letters for unsigned long, which is zero-extended to
64-bit types.  SYSCALL_ULONG_ARG_1 and SYSCALL_ULONG_ARG_2 are passed
to syscall-template.S for the first and the second unsigned long int
arguments if PSEUDOS_HAVE_ULONG_INDICES is defined.  They are used by
x32 to zero-extend 32-bit arguments to 64 bits.

Tested on i386, x86-64 and x32 as well as with build-many-glibcs.py.

sysdeps/unix/make-syscalls.sh
sysdeps/unix/syscall-template.S
sysdeps/unix/syscalls.list
sysdeps/unix/sysv/linux/syscalls.list
sysdeps/unix/sysv/linux/x86_64/sysdep.h
sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h

index c07626677f06d615bd03fdb4ba2a0c4e9591698d..4f6c3490a20bc3eb34f11f1e7aab0ddec7e82e5d 100644 (file)
@@ -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 int (32-bit types are zero-extended to 64-bit types)
 # 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,27 @@ while read file srcfile caller syscall args strong weak; do
   ?:?????????) nargs=9;;
   esac
 
+  # Derive the unsigned long int arguments from the argument signature
+  ulong_arg_1=0
+  ulong_arg_2=0
+  ulong_count=0
+  for U in $(echo $args | sed -e "s/.*:/:/" | grep -ob U)
+  do
+    ulong_count=$(expr $ulong_count + 1)
+    ulong_arg=$(echo $U | sed -e "s/:U//")
+    case $ulong_count in
+    1)
+      ulong_arg_1=$ulong_arg
+      ;;
+    2)
+      ulong_arg_2=$ulong_arg
+      ;;
+    *)
+      echo >&2 "$0: Too many unsigned long int arguments for syscall ($strong $weak)"
+      exit 2
+    esac
+  done
+
   # Make sure only the first syscall rule is used, if multiple dirs
   # define the same syscall.
   echo ''
@@ -245,6 +267,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'; \\
index cf6c7a58fbf094b7ef6027b16136fcc756a6e20e..f807a8603f623b783d93379313e1da06e2e7b119 100644 (file)
    defining a few macros:
        SYSCALL_NAME            syscall name
        SYSCALL_NARGS           number of arguments this call takes
+       SYSCALL_ULONG_ARG_1     the first unsigned long int argument this
+                               call takes.  0 means that there are no
+                               unsigned long int arguments.
+       SYSCALL_ULONG_ARG_2     the second unsigned long int argument this
+                               call takes.  0 means that there is at most
+                               one unsigned long int argument.
        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)
 /* 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 PSEUDOS_HAVE_ULONG_INDICES is defined, PSEUDO and T_PSEUDO macros
+   have 2 extra arguments for unsigned long int arguments:
+     Extra argument 1: Position of the first unsigned long int argument.
+     Extra argument 2: Position of the second unsigned long int argument.
+ */
+#ifndef PSEUDOS_HAVE_ULONG_INDICES
+# undef SYSCALL_ULONG_ARG_1
+# define SYSCALL_ULONG_ARG_1 0
+#endif
+
+#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)
 /* 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 +99,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 +113,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)
 
index e8f8718b04e4b9996fab747703741d9257c0ba6b..766d1664aaa7ee959a26256de3de952466c0ea50 100644 (file)
@@ -37,16 +37,16 @@ kill                -       kill            i:ii    __kill          kill
 link           -       link            i:ss    __link          link
 listen         -       listen          i:ii    __listen        listen
 lseek          -       lseek           i:iii   __libc_lseek    __lseek lseek
-madvise                -       madvise         i:pii   __madvise       madvise
+madvise                -       madvise         i:pUi   __madvise       madvise
 mkdir          -       mkdir           i:si    __mkdir         mkdir
 mmap           -       mmap            b:aniiii __mmap         mmap
-mprotect       -       mprotect        i:aii   __mprotect      mprotect
-munmap         -       munmap          i:ai    __munmap        munmap
+mprotect       -       mprotect        i:aUi   __mprotect      mprotect
+munmap         -       munmap          i:aU    __munmap        munmap
 open           -       open            Ci:siv  __libc_open __open open
 profil         -       profil          i:piii  __profil        profil
 ptrace         -       ptrace          i:iiii  ptrace
 read           -       read            Ci:ibn  __libc_read     __read read
-readlink       -       readlink        i:spi   __readlink      readlink
+readlink       -       readlink        i:spU   __readlink      readlink
 readv          -       readv           Ci:ipi  __readv         readv
 reboot         -       reboot          i:i     reboot
 recv           -       recv            Ci:ibni __libc_recv     recv
index e40f9934958aa8986b3c51032bbf087240620f43..1b1010d4c80432e68332ce7170adfea76c303184 100644 (file)
@@ -32,12 +32,12 @@ ioperm              -       ioperm          i:iii   ioperm
 iopl           -       iopl            i:i     iopl
 klogctl                EXTRA   syslog          i:isi   klogctl
 lchown         -       lchown          i:sii   __lchown        lchown
-mincore                -       mincore         i:anV   mincore
-mlock          -       mlock           i:bn    mlock
+mincore                -       mincore         i:aUV   mincore
+mlock          -       mlock           i:bU    mlock
 mlockall       -       mlockall        i:i     mlockall
-mount          EXTRA   mount           i:sssip __mount mount
-mremap         EXTRA   mremap          b:ainip __mremap        mremap
-munlock                -       munlock         i:ai    munlock
+mount          EXTRA   mount           i:sssUp __mount mount
+mremap         EXTRA   mremap          b:aUUip __mremap        mremap
+munlock                -       munlock         i:aU    munlock
 munlockall     -       munlockall      i:      munlockall
 nfsservctl     EXTRA   nfsservctl      i:ipp   __compat_nfsservctl     nfsservctl@GLIBC_2.0:GLIBC_2.28
 pipe           -       pipe            i:f     __pipe          pipe
@@ -46,7 +46,7 @@ pivot_root    EXTRA   pivot_root      i:ss    pivot_root
 prctl          EXTRA   prctl           i:iiiii __prctl         prctl
 query_module   EXTRA   query_module    i:sipip __compat_query_module   query_module@GLIBC_2.0:GLIBC_2.23
 quotactl       EXTRA   quotactl        i:isip  quotactl
-remap_file_pages -     remap_file_pages i:piiii        __remap_file_pages remap_file_pages
+remap_file_pages -     remap_file_pages i:pUiUi        __remap_file_pages remap_file_pages
 sched_getp     -       sched_getparam  i:ip    __sched_getparam        sched_getparam
 sched_gets     -       sched_getscheduler      i:i     __sched_getscheduler    sched_getscheduler
 sched_primax   -       sched_get_priority_max  i:i     __sched_get_priority_max        sched_get_priority_max
@@ -54,7 +54,7 @@ sched_primin  -       sched_get_priority_min  i:i     __sched_get_priority_min        sched_get_pri
 sched_setp     -       sched_setparam  i:ip    __sched_setparam        sched_setparam
 sched_sets     -       sched_setscheduler      i:iip   __sched_setscheduler    sched_setscheduler
 sched_yield    -       sched_yield     i:      __sched_yield   sched_yield
-sendfile       -       sendfile        i:iipi  sendfile
+sendfile       -       sendfile        i:iipU  sendfile
 sendfile64     -       sendfile64      i:iipi  sendfile64
 setfsgid       EXTRA   setfsgid        i:i     setfsgid
 setfsuid       EXTRA   setfsuid        i:i     setfsuid
@@ -71,7 +71,7 @@ chown         -       chown           i:sii   __libc_chown    __chown chown
 fchownat       -       fchownat        i:isiii fchownat
 linkat         -       linkat          i:isisi linkat
 mkdirat                -       mkdirat         i:isi   mkdirat
-readlinkat     -       readlinkat      i:issi  readlinkat
+readlinkat     -       readlinkat      i:issU  readlinkat
 symlinkat      -       symlinkat       i:sis   symlinkat
 unlinkat       -       unlinkat        i:isi   unlinkat
 
index 85f8f948201c857520119d12c841e886970cce8f..bf36875477460031bd98bba79fe3852267d50dd7 100644 (file)
 #  define SYSCALL_ERROR_LABEL syscall_error
 # endif
 
+/* PSEUDO and T_PSEUDO macros have 2 extra arguments for unsigned long
+   int arguments.  */
+# define PSEUDOS_HAVE_ULONG_INDICES 1
+
+# 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, ulong_arg_1, ulong_arg_2) \
+  .text;                                                             \
+  ENTRY (name)                                                       \
+    DO_CALL (syscall_name, args, ulong_arg_1, ulong_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)                                                    \
   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, ulong_arg_1, ulong_arg_2) \
+  .text;                                                             \
+  ENTRY (name)                                                       \
+    DO_CALL (syscall_name, args, ulong_arg_1, ulong_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) \
 # 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, ulong_arg_1, ulong_arg_2) \
+  .text;                                                       \
+  ENTRY (name)                                                 \
+    DO_CALL (syscall_name, args, ulong_arg_1, ulong_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) \
     Syscalls of more than 6 arguments are not supported.  */
 
 # undef        DO_CALL
-# define DO_CALL(syscall_name, args)           \
+# define DO_CALL(syscall_name, args, ulong_arg_1, ulong_arg_2) \
     DOARGS_##args                              \
+    ZERO_EXTEND_##ulong_arg_1                  \
+    ZERO_EXTEND_##ulong_arg_2                  \
     movl $SYS_ify (syscall_name), %eax;                \
     syscall;
 
 # define DOARGS_5 DOARGS_4
 # define DOARGS_6 DOARGS_5
 
+# define ZERO_EXTEND_0 /* nothing */
+# define ZERO_EXTEND_1 /* nothing */
+# define ZERO_EXTEND_2 /* nothing */
+# define ZERO_EXTEND_3 /* nothing */
+# define ZERO_EXTEND_4 /* nothing */
+# define ZERO_EXTEND_5 /* nothing */
+# define ZERO_EXTEND_6 /* nothing */
+
 #else  /* !__ASSEMBLER__ */
 
 /* Registers clobbered by syscall.  */
index a37d520f8634035239babc01b0840d9d8be56a71..62e6f8fe11fa31a10009d7c2bf0281f657dd35ab 100644 (file)
 #undef LO_HI_LONG
 #define LO_HI_LONG(val) (val)
 
-#ifndef __ASSEMBLER__
+#ifdef __ASSEMBLER__
+/* Zero-extend 32-bit unsigned long int arguments to 64 bits.  */
+# undef ZERO_EXTEND_1
+# define ZERO_EXTEND_1 movl %edi, %edi;
+# undef ZERO_EXTEND_2
+# define ZERO_EXTEND_2 movl %esi, %esi;
+# undef ZERO_EXTEND_3
+# define ZERO_EXTEND_3 movl %edx, %edx;
+# if SYSCALL_ULONG_ARG_1 == 4 || SYSCALL_ULONG_ARG_2 == 4
+#  undef DOARGS_4
+#  define DOARGS_4 movl %ecx, %r10d;
+# else
+#  undef ZERO_EXTEND_4
+#  define ZERO_EXTEND_4 movl %r10d, %r10d;
+# endif
+# undef ZERO_EXTEND_5
+# define ZERO_EXTEND_5 movl %r8d, %r8d;
+# undef ZERO_EXTEND_6
+# define ZERO_EXTEND_6 movl %r9d, %r9d;
+#else /* !__ASSEMBLER__ */
 # undef ARGIFY
 /* Enforce zero-extension for pointers and array system call arguments.
    For integer types, extend to int64_t (the full register) using a
This page took 0.052938 seconds and 5 git commands to generate.