From patchwork Mon Apr 13 14:25:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 38811 Return-Path: X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pl1-x62f.google.com (mail-pl1-x62f.google.com [IPv6:2607:f8b0:4864:20::62f]) by sourceware.org (Postfix) with ESMTPS id B11613887014 for ; Mon, 13 Apr 2020 14:25:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org B11613887014 Received: by mail-pl1-x62f.google.com with SMTP id w3so3442203plz.5 for ; Mon, 13 Apr 2020 07:25:19 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=qNPtjCnrhei72NEiC5ZLF7dxlECKg/Z0jXP0145Tf+0=; b=p0xuKL5fnPFENX2MjIlq8u1C4fNUYrFZ5Q1vkASthbCGCI4SV4zGVYT71LL5hWxIMy kMdJnap8gNEO4mGL1YewJMpFL9qfKgp+zOcsFKCPexRYCQbA5MApRNJkqRPrlTtiuKjT n4nvby73+J8ZOG4cpAVSGnxCGEOYyvLaahKnvVL+o2tnvt7vHVQri3P6W7xbwk4HFa4c 93Lz+igPkhO3ALBueaQPqmAPRrujVAFkAhwxAaM+TnDJsc1XtX7/Sn8n5ju41PoCrgxU AgiPVL9S0FXpi7uWCx32/LLD8QEyOn1QKRDjldk2d8o4srXFEljedEUhcXWuyXQu/Oio u5mw== X-Gm-Message-State: AGi0PuaWOD4IGAObFBhKTl74IcGaFo9x38q0Yl9FycRdhZ8b3fOBSauN uBYfDG1j0vRHKhZZVmWNxfE= X-Google-Smtp-Source: APiQypIDxvZtZShDlp5Ka2D4AcGWoSW+zqa2EJ+MvEDFeqBdFg7NUDQ0U51FDXIhQ8x51Tyth/OqvQ== X-Received: by 2002:a17:902:9308:: with SMTP id bc8mr17998924plb.278.1586787918657; Mon, 13 Apr 2020 07:25:18 -0700 (PDT) Received: from gnu-cfl-2.localdomain (c-69-181-90-243.hsd1.ca.comcast.net. [69.181.90.243]) by smtp.gmail.com with ESMTPSA id nk12sm9478285pjb.41.2020.04.13.07.25.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Apr 2020 07:25:17 -0700 (PDT) Received: from gnu-cfl-2.localdomain (localhost [IPv6:::1]) by gnu-cfl-2.localdomain (Postfix) with ESMTP id 98F98C0453; Mon, 13 Apr 2020 07:25:16 -0700 (PDT) From: "H.J. Lu" To: libc-alpha@sourceware.org Subject: [PATCH 1/3] Add SYSCALL_ULONG_ARG_[12] to pass long to syscall [BZ #25810] Date: Mon, 13 Apr 2020 07:25:13 -0700 Message-Id: <20200413142515.16619-2-hjl.tools@gmail.com> X-Mailer: git-send-email 2.25.2 In-Reply-To: <20200413142515.16619-1-hjl.tools@gmail.com> References: <20200413142515.16619-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-24.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 13 Apr 2020 14:25:21 -0000 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 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 if PSEUDOS_HAVE_4_ARGS 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 | 88 +++++++++++++++++++++ sysdeps/unix/syscall-template.S | 43 +++++++++- sysdeps/unix/syscalls.list | 6 +- sysdeps/unix/sysv/linux/syscalls.list | 14 ++-- sysdeps/unix/sysv/linux/x86_64/sysdep.h | 70 ++++++++++++---- sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h | 20 +++++ 6 files changed, 214 insertions(+), 27 deletions(-) diff --git a/sysdeps/unix/make-syscalls.sh b/sysdeps/unix/make-syscalls.sh index c07626677f..4a28badea6 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 unsigned 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..0824a3c61e 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,27 @@ /* 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_4_ARGS is defined, PSEUDO macros have 4 arguments. */ +#ifndef PSEUDOS_HAVE_4_ARGS +# 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) @@ -56,7 +78,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 +93,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 +107,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/syscalls.list b/sysdeps/unix/syscalls.list index 01c4a0e6b1..e63a8b9d23 100644 --- a/sysdeps/unix/syscalls.list +++ b/sysdeps/unix/syscalls.list @@ -37,11 +37,11 @@ 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 diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list index e40f993495..4d4af84f9f 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 diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h index 24d8b8ec20..06e39212ee 100644 --- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h +++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h @@ -57,13 +57,30 @@ # define SYSCALL_ERROR_LABEL syscall_error # endif +/* PSEUDO macros have 4 arguments. */ +# define PSEUDOS_HAVE_4_ARGS 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 +88,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 +107,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 +191,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 +206,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 5bf9eed80b..2b5cf0c0ea 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h +++ b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h @@ -26,4 +26,24 @@ #undef LO_HI_LONG #define LO_HI_LONG(val) (val) +#ifdef __ASSEMBLER__ +# 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; +#endif /* __ASSEMBLER__ */ + #endif /* linux/x86_64/x32/sysdep.h */ From patchwork Mon Apr 13 14:25:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 38810 Return-Path: X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pf1-x444.google.com (mail-pf1-x444.google.com [IPv6:2607:f8b0:4864:20::444]) by sourceware.org (Postfix) with ESMTPS id 41EAA3887015 for ; Mon, 13 Apr 2020 14:25:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 41EAA3887015 Received: by mail-pf1-x444.google.com with SMTP id v23so4569186pfm.1 for ; Mon, 13 Apr 2020 07:25:20 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=DnvpHw8Eet9JKPugYoc8Rkv6OeteynTjcCzEJpcjnE4=; b=SbNITkdQfM0uMQIiuhs1siFRo0lUmysW4YKkz/rZi5MXTp3C16t0LxL4Qrrkc6RHid sJaKhHLS7L3fvfCUjWNtaIdc7H6x5zcB//QPtgljTabWemFrxNB6ZgjZPkai0EK2rgg6 jYzz3I+bIE9u3ZoqK6mEqzSSvZIaGdcrrv7AJbjojnNOTBZ7wV5Qsm79cfj5wJ5G8WPh 0GknwZfc9SRaTQjT4jIFNd5spCclLvVCnw1hhEHDvsX3Qd7xRYAATkr2EJjRxbTzWy8n pWzCSKm+wclzksRbF8N8haSoXL1IMN5AVk1t2aqveAFBpu692/ZHlhIsSRReSTODfvbo 4XlA== X-Gm-Message-State: AGi0PubicafZg0Ivt7q8wxtwJbRLIKZ+UAEq8Z56g0DDqVkSgb3AxH2n yRKVDFwibO3TUyxH0Umy1wbHstfF X-Google-Smtp-Source: APiQypJALkmfnSI54hZEjh9W6RbSmaUIS4XPV9PjW6b0b/FenXDLCM2a+u9EZMjZQBnlWAQ7Tpeqcw== X-Received: by 2002:aa7:8e13:: with SMTP id c19mr17627018pfr.260.1586787919355; Mon, 13 Apr 2020 07:25:19 -0700 (PDT) Received: from gnu-cfl-2.localdomain (c-69-181-90-243.hsd1.ca.comcast.net. [69.181.90.243]) by smtp.gmail.com with ESMTPSA id q198sm8864415pfc.187.2020.04.13.07.25.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Apr 2020 07:25:18 -0700 (PDT) Received: from gnu-cfl-2.localdomain (localhost [IPv6:::1]) by gnu-cfl-2.localdomain (Postfix) with ESMTP id A3B0BC045C; Mon, 13 Apr 2020 07:25:16 -0700 (PDT) From: "H.J. Lu" To: libc-alpha@sourceware.org Subject: [PATCH 2/3] x32: Properly pass long to syscall [BZ #25810] Date: Mon, 13 Apr 2020 07:25:14 -0700 Message-Id: <20200413142515.16619-3-hjl.tools@gmail.com> X-Mailer: git-send-email 2.25.2 In-Reply-To: <20200413142515.16619-1-hjl.tools@gmail.com> References: <20200413142515.16619-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-24.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 13 Apr 2020 14:25:21 -0000 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 x32 INLINE_SYSCALLs, cast 1. pointer to unsigned long (32 bit). 2. 32-bit unsigned integer to unsigned long long (64 bit). 3. 32-bit integer to long long (64 bit). For void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); we now generate 0: 41 f7 c1 ff 0f 00 00 test $0xfff,%r9d 7: 75 1f jne 28 <__mmap64+0x28> 9: 48 63 d2 movslq %edx,%rdx c: 89 f6 mov %esi,%esi e: 4d 63 c0 movslq %r8d,%r8 11: 4c 63 d1 movslq %ecx,%r10 14: b8 09 00 00 40 mov $0x40000009,%eax 19: 0f 05 syscall That is 1. addr is unchanged. 2. length is zero-extend to 64 bits. 3. prot is sign-extend to 64 bits. 4. flags is sign-extend to 64 bits. 5. fd is sign-extend to 64 bits. 6. offset is unchanged. For int arguments, since kernel uses only the lower 32 bits and ignores the upper 32 bits in 64-bit registers, these work correctly. Tested on x86-64 and x32. There are no code changes on x86-64. --- sysdeps/unix/sysv/linux/x86_64/sysdep.h | 10 ++++++---- sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h index 06e39212ee..93dad97c8f 100644 --- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h +++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h @@ -219,12 +219,14 @@ /* Registers clobbered by syscall. */ # define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx" -/* Create a variable 'name' based on type 'X' to avoid explicit types. - This is mainly used set use 64-bits arguments in x32. */ -#define TYPEFY(X, name) __typeof__ ((X) - (X)) name +/* This also works when X is an array. */ +#define TYPEFY1(X) __typeof__ ((X) - (X)) /* Explicit cast the argument to avoid integer from pointer warning on x32. */ -#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X)) +#define ARGIFY(X) ((TYPEFY1 (X)) (X)) +/* Create a variable 'name' based on type 'X' to avoid explicit types. + This is mainly used set use 64-bits arguments in x32. */ +#define TYPEFY(X, name) __typeof__ (ARGIFY (X) - ARGIFY (X)) name #undef INTERNAL_SYSCALL #define INTERNAL_SYSCALL(name, nr, args...) \ diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h index 2b5cf0c0ea..f3bc7e89df 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h +++ b/sysdeps/unix/sysv/linux/x86_64/x32/sysdep.h @@ -44,6 +44,24 @@ # define ZERO_EXTEND_5 movl %r8d, %r8d; # undef ZERO_EXTEND_6 # define ZERO_EXTEND_6 movl %r9d, %r9d; +#else /*! __ASSEMBLER__ */ +# undef ARGIFY +/* For x32, cast + 1. pointer to unsigned long (32 bit). + 2. 32-bit unsigned integer to unsigned long long (64 bit). + 3. 32-bit integer to long long (64 bit). + */ +# define ARGIFY(X) \ + ({ \ + _Pragma ("GCC diagnostic push"); \ + _Pragma ("GCC diagnostic ignored \"-Wpointer-to-int-cast\""); \ + (__builtin_classify_type (X) == 5 \ + ? (unsigned long) (X) \ + : ((sizeof (X) <= 4 && (TYPEFY1 (X)) 0 < (TYPEFY1 (X)) -1) \ + ? (unsigned long long) (X) \ + : (long long) (X))); \ + _Pragma ("GCC diagnostic pop"); \ + }) #endif /* __ASSEMBLER__ */ #endif /* linux/x86_64/x32/sysdep.h */ From patchwork Mon Apr 13 14:25:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 38809 Return-Path: X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pl1-x641.google.com (mail-pl1-x641.google.com [IPv6:2607:f8b0:4864:20::641]) by sourceware.org (Postfix) with ESMTPS id 4BC54388700B for ; Mon, 13 Apr 2020 14:25:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 4BC54388700B Received: by mail-pl1-x641.google.com with SMTP id k18so3436561pll.6 for ; Mon, 13 Apr 2020 07:25:19 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=QThm5FSTrlxN+7svNFP11QryPz9fgOMXBTZTMCI5Ql4=; b=BnJDO9eNtu49HPjsuDKSXTJ959o4r2bLdZqbk9drqGiUipOQsszrCmlgjrP/IK/Hr6 K6PtAWFchlCPFl3ziS7h/kGokBsOMGTaDRzDeWhVezamQD8kMLMSoe9W6B7qUXGUhq+G pogLCRTpFioyikbhfZwtxuvfAIJUmtISBjWiFmq4BhVKT15KH/BFTZ/LZ55fd6joklGp VJ/tZgvEeUovtBhEb6vxsnHoFuQZ9CaHID9zdfQMxxU1vfQq0HueZKjKeHHVLExVRj2H 6c66c/0p3gatOTMbonS4QsSnZn+T7c7RGdsUw5e28NYnPYkTxwG3FIxh7iZ1zxzG8ksR sqDA== X-Gm-Message-State: AGi0Puah0FZ+DsuDTq5KLK1RB7/tRZO4A2kLO/IVFaRqsGDwQLsHCX5q ZYb2Ckt3TmGjNj/Nibpqbvc= X-Google-Smtp-Source: APiQypJd0a0ZFcUOD2N1bG1ZvnBiM5P5tn27UzS0Qcx3XcDVIZven2zR4pFgl8txNNNeO9w585MLRg== X-Received: by 2002:a17:902:ead4:: with SMTP id p20mr18049584pld.129.1586787918402; Mon, 13 Apr 2020 07:25:18 -0700 (PDT) Received: from gnu-cfl-2.localdomain (c-69-181-90-243.hsd1.ca.comcast.net. [69.181.90.243]) by smtp.gmail.com with ESMTPSA id lj14sm9129018pjb.25.2020.04.13.07.25.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Apr 2020 07:25:17 -0700 (PDT) Received: from gnu-cfl-2.localdomain (localhost [IPv6:::1]) by gnu-cfl-2.localdomain (Postfix) with ESMTP id A4C60C04DA; Mon, 13 Apr 2020 07:25:16 -0700 (PDT) From: "H.J. Lu" To: libc-alpha@sourceware.org Subject: [PATCH 3/3] Add a syscall test for [BZ #25810] Date: Mon, 13 Apr 2020 07:25:15 -0700 Message-Id: <20200413142515.16619-4-hjl.tools@gmail.com> X-Mailer: git-send-email 2.25.2 In-Reply-To: <20200413142515.16619-1-hjl.tools@gmail.com> References: <20200413142515.16619-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-24.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 13 Apr 2020 14:25:20 -0000 Add a test to pass 64-bit long arguments to syscall with undefined upper 32 bits on ILP32 systems. Tested on i386, x86-64 and x32 as well as with build-many-glibcs.py. --- misc/Makefile | 2 +- misc/tst-syscalls.c | 146 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+), 1 deletion(-) 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 + . */ + +#include +#include +#include +#include +#include +#include + +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