diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2020-04-29 05:35:34 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2020-04-29 05:35:34 -0700 |
commit | 2ad5d0845d80589d0adf86593bd36a7c71a521f8 (patch) | |
tree | 81bc0b7de7e0b93604944ed70e4125866547eb39 /sysdeps/unix/sysv/linux | |
parent | 9207e30d3f070712df6c4175547094be112454d2 (diff) | |
download | glibc-2ad5d0845d80589d0adf86593bd36a7c71a521f8.tar.gz glibc-2ad5d0845d80589d0adf86593bd36a7c71a521f8.tar.xz glibc-2ad5d0845d80589d0adf86593bd36a7c71a521f8.zip |
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.
Diffstat (limited to 'sysdeps/unix/sysv/linux')
-rw-r--r-- | sysdeps/unix/sysv/linux/syscalls.list | 16 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/x86_64/sysdep.h | 71 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h | 21 |
3 files changed, 85 insertions, 23 deletions
diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list index e40f993495..1b1010d4c8 100644 --- a/sysdeps/unix/sysv/linux/syscalls.list +++ b/sysdeps/unix/sysv/linux/syscalls.list @@ -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 diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h index 85f8f94820..bf36875477 100644 --- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h +++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h @@ -57,13 +57,31 @@ # 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) \ @@ -71,10 +89,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, 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) \ @@ -83,11 +108,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, 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) \ @@ -159,8 +192,10 @@ 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; @@ -172,6 +207,14 @@ # 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. */ diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h index a37d520f86..62e6f8fe11 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h +++ b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h @@ -26,7 +26,26 @@ #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 |