Add SYSCALL_ULONG_ARG_[12] to pass long to syscall [BZ #25810]

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.

(cherry picked from commit 2ad5d0845d)
This commit is contained in:
H.J. Lu 2020-04-29 05:35:34 -07:00
parent 7378e9c520
commit 6bd82f5fd0
6 changed files with 159 additions and 30 deletions

View File

@ -30,6 +30,7 @@
# P: optionally-NULL pointer to typed object (e.g., 2nd argument to gettimeofday) # P: optionally-NULL pointer to typed object (e.g., 2nd argument to gettimeofday)
# s: non-NULL string (e.g., 1st arg to open) # s: non-NULL string (e.g., 1st arg to open)
# S: optionally-NULL string (e.g., 1st arg to acct) # 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: vararg scalar (e.g., optional 3rd arg to open)
# V: byte-per-page vector (3rd arg to mincore) # V: byte-per-page vector (3rd arg to mincore)
# W: wait status, optionally-NULL pointer to int (e.g., 2nd arg of wait4) # W: wait status, optionally-NULL pointer to int (e.g., 2nd arg of wait4)
@ -192,6 +193,27 @@ while read file srcfile caller syscall args strong weak; do
?:?????????) nargs=9;; ?:?????????) nargs=9;;
esac 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 # Make sure only the first syscall rule is used, if multiple dirs
# define the same syscall. # define the same syscall.
echo '' echo ''
@ -254,6 +276,8 @@ while read file srcfile caller syscall args strong weak; do
\$(make-target-directory) \$(make-target-directory)
(echo '#define SYSCALL_NAME $syscall'; \\ (echo '#define SYSCALL_NAME $syscall'; \\
echo '#define SYSCALL_NARGS $nargs'; \\ 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_SYMBOL $strong'; \\
echo '#define SYSCALL_NOERRNO $noerrno'; \\ echo '#define SYSCALL_NOERRNO $noerrno'; \\
echo '#define SYSCALL_ERRVAL $errval'; \\ echo '#define SYSCALL_ERRVAL $errval'; \\

View File

@ -25,6 +25,12 @@
defining a few macros: defining a few macros:
SYSCALL_NAME syscall name SYSCALL_NAME syscall name
SYSCALL_NARGS number of arguments this call takes 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_SYMBOL primary symbol name
SYSCALL_NOERRNO 1 to define a no-errno version (see below) SYSCALL_NOERRNO 1 to define a no-errno version (see below)
SYSCALL_ERRVAL 1 to define an error-value version (see below) SYSCALL_ERRVAL 1 to define an error-value version (see below)
@ -44,9 +50,31 @@
/* This indirection is needed so that SYMBOL gets macro-expanded. */ /* This indirection is needed so that SYMBOL gets macro-expanded. */
#define syscall_hidden_def(SYMBOL) hidden_def (SYMBOL) #define syscall_hidden_def(SYMBOL) hidden_def (SYMBOL)
#define T_PSEUDO(SYMBOL, NAME, N) PSEUDO (SYMBOL, NAME, N) /* If PSEUDOS_HAVE_ULONG_INDICES is defined, PSEUDO and T_PSEUDO macros
#define T_PSEUDO_NOERRNO(SYMBOL, NAME, N) PSEUDO_NOERRNO (SYMBOL, NAME, N) have 2 extra arguments for unsigned long int arguments:
#define T_PSEUDO_ERRVAL(SYMBOL, NAME, N) PSEUDO_ERRVAL (SYMBOL, NAME, N) 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(SYMBOL) PSEUDO_END (SYMBOL)
#define T_PSEUDO_END_NOERRNO(SYMBOL) PSEUDO_END_NOERRNO (SYMBOL) #define T_PSEUDO_END_NOERRNO(SYMBOL) PSEUDO_END_NOERRNO (SYMBOL)
#define T_PSEUDO_END_ERRVAL(SYMBOL) PSEUDO_END_ERRVAL (SYMBOL) #define T_PSEUDO_END_ERRVAL(SYMBOL) PSEUDO_END_ERRVAL (SYMBOL)
@ -56,7 +84,12 @@
/* This kind of system call stub never returns an error. /* This kind of system call stub never returns an error.
We return the return value register to the caller unexamined. */ 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) T_PSEUDO_NOERRNO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
# endif
ret_NOERRNO ret_NOERRNO
T_PSEUDO_END_NOERRNO (SYSCALL_SYMBOL) 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 value, or zero for success. We may massage the kernel's return value
to meet that ABI, but we never set errno here. */ 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) T_PSEUDO_ERRVAL (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
# endif
ret_ERRVAL ret_ERRVAL
T_PSEUDO_END_ERRVAL (SYSCALL_SYMBOL) 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, /* This is a "normal" system call stub: if there is an error,
it returns -1 and sets errno. */ 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) T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
# endif
ret ret
T_PSEUDO_END (SYSCALL_SYMBOL) T_PSEUDO_END (SYSCALL_SYMBOL)

View File

@ -40,16 +40,16 @@ kill - kill i:ii __kill kill
link - link i:ss __link link link - link i:ss __link link
listen - listen i:ii __listen listen listen - listen i:ii __listen listen
lseek - lseek i:iii __libc_lseek __lseek lseek 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 mkdir - mkdir i:si __mkdir mkdir
mmap - mmap b:aniiii __mmap mmap mmap - mmap b:aniiii __mmap mmap
mprotect - mprotect i:aii __mprotect mprotect mprotect - mprotect i:aUi __mprotect mprotect
munmap - munmap i:ai __munmap munmap munmap - munmap i:aU __munmap munmap
open - open Ci:siv __libc_open __open open open - open Ci:siv __libc_open __open open
profil - profil i:piii __profil profil profil - profil i:piii __profil profil
ptrace - ptrace i:iiii ptrace ptrace - ptrace i:iiii ptrace
read - read Ci:ibn __libc_read __read read 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 readv - readv Ci:ipi __readv readv
reboot - reboot i:i reboot reboot - reboot i:i reboot
recv - recv Ci:ibni __libc_recv recv recv - recv Ci:ibni __libc_recv recv

View File

@ -33,12 +33,12 @@ ioperm - ioperm i:iii ioperm
iopl - iopl i:i iopl iopl - iopl i:i iopl
klogctl EXTRA syslog i:isi klogctl klogctl EXTRA syslog i:isi klogctl
lchown - lchown i:sii __lchown lchown lchown - lchown i:sii __lchown lchown
mincore - mincore i:anV mincore mincore - mincore i:aUV mincore
mlock - mlock i:bn mlock mlock - mlock i:bU mlock
mlockall - mlockall i:i mlockall mlockall - mlockall i:i mlockall
mount EXTRA mount i:sssip __mount mount mount EXTRA mount i:sssUp __mount mount
mremap EXTRA mremap b:ainip __mremap mremap mremap EXTRA mremap b:aUUip __mremap mremap
munlock - munlock i:ai munlock munlock - munlock i:aU munlock
munlockall - munlockall i: munlockall munlockall - munlockall i: munlockall
nfsservctl EXTRA nfsservctl i:ipp __compat_nfsservctl nfsservctl@GLIBC_2.0:GLIBC_2.28 nfsservctl EXTRA nfsservctl i:ipp __compat_nfsservctl nfsservctl@GLIBC_2.0:GLIBC_2.28
pipe - pipe i:f __pipe pipe pipe - pipe i:f __pipe pipe
@ -47,7 +47,7 @@ pivot_root EXTRA pivot_root i:ss pivot_root
prctl EXTRA prctl i:iiiii __prctl prctl 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 query_module EXTRA query_module i:sipip __compat_query_module query_module@GLIBC_2.0:GLIBC_2.23
quotactl EXTRA quotactl i:isip quotactl 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_getp - sched_getparam i:ip __sched_getparam sched_getparam
sched_gets - sched_getscheduler i:i __sched_getscheduler sched_getscheduler 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 sched_primax - sched_get_priority_max i:i __sched_get_priority_max sched_get_priority_max
@ -56,7 +56,7 @@ sched_rr_gi - sched_rr_get_interval i:ip __sched_rr_get_interval sched_rr_get_in
sched_setp - sched_setparam i:ip __sched_setparam sched_setparam sched_setp - sched_setparam i:ip __sched_setparam sched_setparam
sched_sets - sched_setscheduler i:iip __sched_setscheduler sched_setscheduler sched_sets - sched_setscheduler i:iip __sched_setscheduler sched_setscheduler
sched_yield - sched_yield i: __sched_yield sched_yield sched_yield - sched_yield i: __sched_yield sched_yield
sendfile - sendfile i:iipi sendfile sendfile - sendfile i:iipU sendfile
sendfile64 - sendfile64 i:iipi sendfile64 sendfile64 - sendfile64 i:iipi sendfile64
setfsgid EXTRA setfsgid i:i setfsgid setfsgid EXTRA setfsgid i:i setfsgid
setfsuid EXTRA setfsuid i:i setfsuid setfsuid EXTRA setfsuid i:i setfsuid
@ -76,7 +76,7 @@ chown - chown i:sii __libc_chown __chown chown
fchownat - fchownat i:isiii fchownat fchownat - fchownat i:isiii fchownat
linkat - linkat i:isisi linkat linkat - linkat i:isisi linkat
mkdirat - mkdirat i:isi mkdirat mkdirat - mkdirat i:isi mkdirat
readlinkat - readlinkat i:issi readlinkat readlinkat - readlinkat i:issU readlinkat
symlinkat - symlinkat i:sis symlinkat symlinkat - symlinkat i:sis symlinkat
unlinkat - unlinkat i:isi unlinkat unlinkat - unlinkat i:isi unlinkat

View File

@ -74,13 +74,31 @@
# define SYSCALL_ERROR_LABEL syscall_error # define SYSCALL_ERROR_LABEL syscall_error
# endif # 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 # undef PSEUDO
# define PSEUDO(name, syscall_name, args) \ # if SYSCALL_ULONG_ARG_1
.text; \ # define PSEUDO(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \
ENTRY (name) \ .text; \
DO_CALL (syscall_name, args); \ ENTRY (name) \
cmpq $-4095, %rax; \ DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2); \
cmpq $-4095, %rax; \
jae SYSCALL_ERROR_LABEL 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 # undef PSEUDO_END
# define PSEUDO_END(name) \ # define PSEUDO_END(name) \
@ -88,10 +106,17 @@
END (name) END (name)
# undef PSEUDO_NOERRNO # undef PSEUDO_NOERRNO
# define PSEUDO_NOERRNO(name, syscall_name, args) \ # if SYSCALL_ULONG_ARG_1
.text; \ # define PSEUDO_NOERRNO(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \
ENTRY (name) \ .text; \
DO_CALL (syscall_name, args) 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 # undef PSEUDO_END_NOERRNO
# define PSEUDO_END_NOERRNO(name) \ # define PSEUDO_END_NOERRNO(name) \
@ -100,11 +125,19 @@
# define ret_NOERRNO ret # define ret_NOERRNO ret
# undef PSEUDO_ERRVAL # undef PSEUDO_ERRVAL
# define PSEUDO_ERRVAL(name, syscall_name, args) \ # if SYSCALL_ULONG_ARG_1
.text; \ # define PSEUDO_ERRVAL(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \
ENTRY (name) \ .text; \
DO_CALL (syscall_name, args); \ ENTRY (name) \
DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2); \
negq %rax 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 # undef PSEUDO_END_ERRVAL
# define PSEUDO_END_ERRVAL(name) \ # define PSEUDO_END_ERRVAL(name) \
@ -176,8 +209,10 @@
Syscalls of more than 6 arguments are not supported. */ Syscalls of more than 6 arguments are not supported. */
# undef DO_CALL # undef DO_CALL
# define DO_CALL(syscall_name, args) \ # define DO_CALL(syscall_name, args, ulong_arg_1, ulong_arg_2) \
DOARGS_##args \ DOARGS_##args \
ZERO_EXTEND_##ulong_arg_1 \
ZERO_EXTEND_##ulong_arg_2 \
movl $SYS_ify (syscall_name), %eax; \ movl $SYS_ify (syscall_name), %eax; \
syscall; syscall;
@ -189,6 +224,14 @@
# define DOARGS_5 DOARGS_4 # define DOARGS_5 DOARGS_4
# define DOARGS_6 DOARGS_5 # 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__ */ #else /* !__ASSEMBLER__ */
/* Define a macro which expands inline into the wrapper code for a system /* Define a macro which expands inline into the wrapper code for a system
call. */ call. */

View File

@ -26,7 +26,26 @@
#undef LO_HI_LONG #undef LO_HI_LONG
#define LO_HI_LONG(val) (val) #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 # undef ARGIFY
/* Enforce zero-extension for pointers and array system call arguments. /* Enforce zero-extension for pointers and array system call arguments.
For integer types, extend to int64_t (the full register) using a For integer types, extend to int64_t (the full register) using a