From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,RDNS_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: (qmail 1979 invoked from network); 11 Mar 2020 23:09:40 -0000 Received-SPF: pass (mother.openwall.net: domain of lists.openwall.com designates 195.42.179.200 as permitted sender) receiver=inbox.vuxu.org; client-ip=195.42.179.200 envelope-from= Received: from unknown (HELO mother.openwall.net) (195.42.179.200) by inbox.vuxu.org with ESMTP; 11 Mar 2020 23:09:40 -0000 Received: (qmail 5874 invoked by uid 550); 11 Mar 2020 23:09:38 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Reply-To: musl@lists.openwall.com Received: (qmail 5841 invoked from network); 11 Mar 2020 23:09:37 -0000 Date: Wed, 11 Mar 2020 19:09:25 -0400 From: Rich Felker To: musl@lists.openwall.com Cc: Andreas =?utf-8?B?RHLDtnNjaGVy?= Message-ID: <20200311230925.GA27158@brightrain.aerifal.cx> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="jRHKVT23PllUwdXP" Content-Disposition: inline Content-Transfer-Encoding: 8bit User-Agent: Mutt/1.5.21 (2010-09-15) Subject: [musl] [PATCH] fix mips syscall asm regressions and kernel bug --jRHKVT23PllUwdXP Content-Type: text/plain; charset=us-ascii Content-Disposition: inline --jRHKVT23PllUwdXP Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="0001-revert-previous-changes-to-mips64-n32-syscall-asm-co.patch" >From a6ab25ff9885a810c8ceba42b9b1ea3badaae879 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 11 Mar 2020 18:43:11 -0400 Subject: [PATCH 1/4] revert previous changes to mips64/n32 syscall asm constraints effectivly revert commit ddc7c4f936c7a90781072f10dbaa122007e939d0 which was wrong; it caused a major regression on Linux versions prior to 2.6.36. old kernels did not properly preserve r2 across syscall restart, and instead restarted with the instruction right before syscall, imposing a contract that the previous instruction must load r2 from an immediate or a register (or memory) not clobbered by the syscall. since other changes were made since, this is not a direct revert, only a functional one. the improved style and removal of redundant constraints are kept. --- arch/mips64/syscall_arch.h | 56 +++++++++++++++++----------------- arch/mipsn32/syscall_arch.h | 61 ++++++++++++++++++++----------------- 2 files changed, 61 insertions(+), 56 deletions(-) diff --git a/arch/mips64/syscall_arch.h b/arch/mips64/syscall_arch.h index 69c429b8..8f6758d3 100644 --- a/arch/mips64/syscall_arch.h +++ b/arch/mips64/syscall_arch.h @@ -16,11 +16,11 @@ static inline long __syscall0(long n) { register long r7 __asm__("$7"); - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); __asm__ __volatile__ ( - "syscall" - : "+&r"(r2), "=r"(r7) - : + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n) : SYSCALL_CLOBBERLIST); return r7 ? -r2 : r2; } @@ -29,11 +29,11 @@ static inline long __syscall1(long n, long a) { register long r4 __asm__("$4") = a; register long r7 __asm__("$7"); - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); __asm__ __volatile__ ( - "syscall" - : "+&r"(r2), "=r"(r7) - : "r"(r4) + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n), "r"(r4) : SYSCALL_CLOBBERLIST); return r7 ? -r2 : r2; } @@ -43,12 +43,12 @@ static inline long __syscall2(long n, long a, long b) register long r4 __asm__("$4") = a; register long r5 __asm__("$5") = b; register long r7 __asm__("$7"); - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); __asm__ __volatile__ ( - "syscall" - : "+&r"(r2), "=r"(r7) - : "r"(r4), "r"(r5) + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n), "r"(r4), "r"(r5) : SYSCALL_CLOBBERLIST); return r7 ? -r2 : r2; } @@ -59,12 +59,12 @@ static inline long __syscall3(long n, long a, long b, long c) register long r5 __asm__("$5") = b; register long r6 __asm__("$6") = c; register long r7 __asm__("$7"); - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); __asm__ __volatile__ ( - "syscall" - : "+&r"(r2), "=r"(r7) - : "r"(r4), "r"(r5), "r"(r6) + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST); return r7 ? -r2 : r2; } @@ -75,12 +75,12 @@ static inline long __syscall4(long n, long a, long b, long c, long d) register long r5 __asm__("$5") = b; register long r6 __asm__("$6") = c; register long r7 __asm__("$7") = d; - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); __asm__ __volatile__ ( - "syscall" - : "+&r"(r2), "+r"(r7) - : "r"(r4), "r"(r5), "r"(r6) + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "+r"(r7) + : "ir"(n), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST); return r7 ? -r2 : r2; } @@ -92,12 +92,12 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e) register long r6 __asm__("$6") = c; register long r7 __asm__("$7") = d; register long r8 __asm__("$8") = e; - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); __asm__ __volatile__ ( - "syscall" - : "+&r"(r2), "+r"(r7) - : "r"(r4), "r"(r5), "r"(r6), "r"(r8) + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "+r"(r7) + : "ir"(n), "r"(r4), "r"(r5), "r"(r6), "r"(r8) : SYSCALL_CLOBBERLIST); return r7 ? -r2 : r2; } @@ -110,12 +110,12 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo register long r7 __asm__("$7") = d; register long r8 __asm__("$8") = e; register long r9 __asm__("$9") = f; - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); __asm__ __volatile__ ( - "syscall" - : "+&r"(r2), "+r"(r7) - : "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9) + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "+r"(r7) + : "ir"(n), "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9) : SYSCALL_CLOBBERLIST); return r7 ? -r2 : r2; } diff --git a/arch/mipsn32/syscall_arch.h b/arch/mipsn32/syscall_arch.h index c1a4b7da..bc29e318 100644 --- a/arch/mipsn32/syscall_arch.h +++ b/arch/mipsn32/syscall_arch.h @@ -16,11 +16,11 @@ static inline long __syscall0(long n) { register long r7 __asm__("$7"); - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); __asm__ __volatile__ ( - "syscall" - : "+&r"(r2), "=r"(r7) - : + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n) : SYSCALL_CLOBBERLIST); return r7 ? -r2 : r2; } @@ -29,11 +29,11 @@ static inline long __syscall1(long n, long a) { register long r4 __asm__("$4") = a; register long r7 __asm__("$7"); - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); __asm__ __volatile__ ( - "syscall" - : "+&r"(r2), "=r"(r7) - : "r"(r4) + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n), "r"(r4) : SYSCALL_CLOBBERLIST); return r7 ? -r2 : r2; } @@ -43,11 +43,12 @@ static inline long __syscall2(long n, long a, long b) register long r4 __asm__("$4") = a; register long r5 __asm__("$5") = b; register long r7 __asm__("$7"); - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); + __asm__ __volatile__ ( - "syscall" - : "+&r"(r2), "=r"(r7) - : "r"(r4), "r"(r5) + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n), "r"(r4), "r"(r5) : SYSCALL_CLOBBERLIST); return r7 ? -r2 : r2; } @@ -58,11 +59,12 @@ static inline long __syscall3(long n, long a, long b, long c) register long r5 __asm__("$5") = b; register long r6 __asm__("$6") = c; register long r7 __asm__("$7"); - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); + __asm__ __volatile__ ( - "syscall" - : "+&r"(r2), "=r"(r7) - : "r"(r4), "r"(r5), "r"(r6) + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST); return r7 ? -r2 : r2; } @@ -73,11 +75,12 @@ static inline long __syscall4(long n, long a, long b, long c, long d) register long r5 __asm__("$5") = b; register long r6 __asm__("$6") = c; register long r7 __asm__("$7") = d; - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); + __asm__ __volatile__ ( - "syscall" - : "+&r"(r2), "+r"(r7) - : "r"(r4), "r"(r5), "r"(r6) + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "+r"(r7) + : "ir"(n), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST); return r7 ? -r2 : r2; } @@ -89,11 +92,12 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e) register long r6 __asm__("$6") = c; register long r7 __asm__("$7") = d; register long r8 __asm__("$8") = e; - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); + __asm__ __volatile__ ( - "syscall" - : "+&r"(r2), "+r"(r7) - : "r"(r4), "r"(r5), "r"(r6), "r"(r8) + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "+r"(r7) + : "ir"(n), "r"(r4), "r"(r5), "r"(r6), "r"(r8) : SYSCALL_CLOBBERLIST); return r7 ? -r2 : r2; } @@ -106,11 +110,12 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo register long r7 __asm__("$7") = d; register long r8 __asm__("$8") = e; register long r9 __asm__("$9") = f; - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); + __asm__ __volatile__ ( - "syscall" - : "+&r"(r2), "+r"(r7) - : "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9) + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "+r"(r7) + : "ir"(n), "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9) : SYSCALL_CLOBBERLIST); return r7 ? -r2 : r2; } -- 2.21.0 --jRHKVT23PllUwdXP Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="0002-revert-previous-changes-to-mips-32-bit-o32-syscall-a.patch" >From 6182ff1f35675c60c201be73e60654c15af77c2f Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 11 Mar 2020 18:50:21 -0400 Subject: [PATCH 2/4] revert previous changes to mips (32-bit, o32) syscall asm exactly revert commit 604f8d3d8b08ee4f548de193050ef93a7753c2e0. it's wrong for the same reason as a6ab25ff9885a810c8ceba42b9b1ea3badaae879 but does not have to deal with conflicting changes since. improvements that were valid will be added back as a separate commit. --- arch/mips/syscall_arch.h | 63 ++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/arch/mips/syscall_arch.h b/arch/mips/syscall_arch.h index f821e73f..a3812188 100644 --- a/arch/mips/syscall_arch.h +++ b/arch/mips/syscall_arch.h @@ -18,11 +18,10 @@ static inline long __syscall0(long n) { register long r7 __asm__("$7"); - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); __asm__ __volatile__ ( - "syscall" - : "+r"(r2), "=r"(r7) - : + "addu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7) : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); return r7 ? -r2 : r2; } @@ -31,11 +30,11 @@ static inline long __syscall1(long n, long a) { register long r4 __asm__("$4") = a; register long r7 __asm__("$7"); - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); __asm__ __volatile__ ( - "syscall" - : "+r"(r2), "=r"(r7) - : "r"(r4) + "addu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7), + "r"(r4) : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); return r7 ? -r2 : r2; } @@ -45,11 +44,11 @@ static inline long __syscall2(long n, long a, long b) register long r4 __asm__("$4") = a; register long r5 __asm__("$5") = b; register long r7 __asm__("$7"); - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); __asm__ __volatile__ ( - "syscall" - : "+r"(r2), "=r"(r7) - : "r"(r4), "r"(r5) + "addu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7), + "r"(r4), "r"(r5) : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); return r7 ? -r2 : r2; } @@ -60,11 +59,11 @@ static inline long __syscall3(long n, long a, long b, long c) register long r5 __asm__("$5") = b; register long r6 __asm__("$6") = c; register long r7 __asm__("$7"); - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); __asm__ __volatile__ ( - "syscall" - : "+r"(r2), "=r"(r7) - : "r"(r4), "r"(r5), "r"(r6) + "addu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7), + "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); return r7 ? -r2 : r2; } @@ -75,11 +74,11 @@ static inline long __syscall4(long n, long a, long b, long c, long d) register long r5 __asm__("$5") = b; register long r6 __asm__("$6") = c; register long r7 __asm__("$7") = d; - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); __asm__ __volatile__ ( - "syscall" - : "+r"(r2), "+r"(r7) - : "r"(r4), "r"(r5), "r"(r6) + "addu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7), + "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); return r7 ? -r2 : r2; } @@ -91,13 +90,13 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e) register long r6 __asm__("$6") = c; register long r7 __asm__("$7") = d; register long r8 __asm__("$8") = e; - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); __asm__ __volatile__ ( "subu $sp,$sp,32 ; sw $8,16($sp) ; " - "syscall ;" + "addu $2,$0,%3 ; syscall ;" "addu $sp,$sp,32" - : "+r"(r2), "+r"(r7), "+r"(r8) - : "r"(r4), "r"(r5), "r"(r6) + : "=&r"(r2), "=r"(r7), "+r"(r8) + : "ir"(n), "0"(r2), "1"(r7), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST, "$9", "$10"); return r7 ? -r2 : r2; } @@ -110,13 +109,13 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo register long r7 __asm__("$7") = d; register long r8 __asm__("$8") = e; register long r9 __asm__("$9") = f; - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); __asm__ __volatile__ ( "subu $sp,$sp,32 ; sw $8,16($sp) ; sw $9,20($sp) ; " - "syscall ;" + "addu $2,$0,%4 ; syscall ;" "addu $sp,$sp,32" - : "+r"(r2), "+r"(r7), "+r"(r8), "+r"(r9) - : "r"(r4), "r"(r5), "r"(r6) + : "=&r"(r2), "=r"(r7), "+r"(r8), "+r"(r9) + : "ir"(n), "0"(r2), "1"(r7), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST, "$10"); return r7 ? -r2 : r2; } @@ -130,13 +129,13 @@ static inline long __syscall7(long n, long a, long b, long c, long d, long e, lo register long r8 __asm__("$8") = e; register long r9 __asm__("$9") = f; register long r10 __asm__("$10") = g; - register long r2 __asm__("$2") = n; + register long r2 __asm__("$2"); __asm__ __volatile__ ( "subu $sp,$sp,32 ; sw $8,16($sp) ; sw $9,20($sp) ; sw $10,24($sp) ; " - "syscall ;" + "addu $2,$0,%5 ; syscall ;" "addu $sp,$sp,32" - : "+r"(r2), "+r"(r7), "+r"(r8), "+r"(r9), "+r"(r10) - : "r"(r4), "r"(r5), "r"(r6) + : "=&r"(r2), "=r"(r7), "+r"(r8), "+r"(r9), "+r"(r10) + : "ir"(n), "0"(r2), "1"(r7), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST); return r7 ? -r2 : r2; } -- 2.21.0 --jRHKVT23PllUwdXP Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="0003-restore-mips-syscall-asm-improvements-from-reverted-.patch" >From dd656a205b5f1d0513f7c71c70c786af1e248304 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 11 Mar 2020 18:58:38 -0400 Subject: [PATCH 3/4] restore mips syscall asm improvements from reverted change in addition to the wrong change to loading of r2, commit 604f8d3d8b08ee4f548de193050ef93a7753c2e0 removed some useless, redundant, and possibly undefined constraints. bring back the good parts. --- arch/mips/syscall_arch.h | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/arch/mips/syscall_arch.h b/arch/mips/syscall_arch.h index a3812188..0a5d6d8f 100644 --- a/arch/mips/syscall_arch.h +++ b/arch/mips/syscall_arch.h @@ -21,7 +21,8 @@ static inline long __syscall0(long n) register long r2 __asm__("$2"); __asm__ __volatile__ ( "addu $2,$0,%2 ; syscall" - : "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7) + : "=&r"(r2), "=r"(r7) + : "ir"(n) : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); return r7 ? -r2 : r2; } @@ -33,8 +34,8 @@ static inline long __syscall1(long n, long a) register long r2 __asm__("$2"); __asm__ __volatile__ ( "addu $2,$0,%2 ; syscall" - : "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7), - "r"(r4) + : "=&r"(r2), "=r"(r7) + : "ir"(n), "r"(r4) : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); return r7 ? -r2 : r2; } @@ -47,8 +48,8 @@ static inline long __syscall2(long n, long a, long b) register long r2 __asm__("$2"); __asm__ __volatile__ ( "addu $2,$0,%2 ; syscall" - : "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7), - "r"(r4), "r"(r5) + : "=&r"(r2), "=r"(r7) + : "ir"(n), "r"(r4), "r"(r5) : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); return r7 ? -r2 : r2; } @@ -62,8 +63,8 @@ static inline long __syscall3(long n, long a, long b, long c) register long r2 __asm__("$2"); __asm__ __volatile__ ( "addu $2,$0,%2 ; syscall" - : "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7), - "r"(r4), "r"(r5), "r"(r6) + : "=&r"(r2), "=r"(r7) + : "ir"(n), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); return r7 ? -r2 : r2; } @@ -77,8 +78,8 @@ static inline long __syscall4(long n, long a, long b, long c, long d) register long r2 __asm__("$2"); __asm__ __volatile__ ( "addu $2,$0,%2 ; syscall" - : "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7), - "r"(r4), "r"(r5), "r"(r6) + : "=&r"(r2), "+r"(r7) + : "ir"(n), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); return r7 ? -r2 : r2; } @@ -95,8 +96,8 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e) "subu $sp,$sp,32 ; sw $8,16($sp) ; " "addu $2,$0,%3 ; syscall ;" "addu $sp,$sp,32" - : "=&r"(r2), "=r"(r7), "+r"(r8) - : "ir"(n), "0"(r2), "1"(r7), "r"(r4), "r"(r5), "r"(r6) + : "=&r"(r2), "+r"(r7), "+r"(r8) + : "ir"(n), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST, "$9", "$10"); return r7 ? -r2 : r2; } @@ -114,8 +115,8 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo "subu $sp,$sp,32 ; sw $8,16($sp) ; sw $9,20($sp) ; " "addu $2,$0,%4 ; syscall ;" "addu $sp,$sp,32" - : "=&r"(r2), "=r"(r7), "+r"(r8), "+r"(r9) - : "ir"(n), "0"(r2), "1"(r7), "r"(r4), "r"(r5), "r"(r6) + : "=&r"(r2), "+r"(r7), "+r"(r8), "+r"(r9) + : "ir"(n), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST, "$10"); return r7 ? -r2 : r2; } @@ -134,8 +135,8 @@ static inline long __syscall7(long n, long a, long b, long c, long d, long e, lo "subu $sp,$sp,32 ; sw $8,16($sp) ; sw $9,20($sp) ; sw $10,24($sp) ; " "addu $2,$0,%5 ; syscall ;" "addu $sp,$sp,32" - : "=&r"(r2), "=r"(r7), "+r"(r8), "+r"(r9), "+r"(r10) - : "ir"(n), "0"(r2), "1"(r7), "r"(r4), "r"(r5), "r"(r6) + : "=&r"(r2), "+r"(r7), "+r"(r8), "+r"(r9), "+r"(r10) + : "ir"(n), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST); return r7 ? -r2 : r2; } -- 2.21.0 --jRHKVT23PllUwdXP Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename="0004-work-around-negated-error-code-bug-on-some-mips-kern.patch" Content-Transfer-Encoding: 8bit >From a102a531615ac2eed153c37eb6ae44386573a04a Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 11 Mar 2020 19:02:52 -0400 Subject: [PATCH 4/4] work around negated error code bug on some mips kernels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit on all mips variants, Linux did (and maybe still does) have some syscall return paths that wrongly return both the error flag in r7 and a negated error code in r2. in particular this happened for at least some causes of ENOSYS. add an extra check to only negate the error code if it's positive to begin with. bug report and concept for patch by Andreas Dröscher. --- arch/mips/syscall_arch.h | 16 ++++++++-------- arch/mips64/syscall_arch.h | 14 +++++++------- arch/mipsn32/syscall_arch.h | 14 +++++++------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/arch/mips/syscall_arch.h b/arch/mips/syscall_arch.h index 0a5d6d8f..fc301db8 100644 --- a/arch/mips/syscall_arch.h +++ b/arch/mips/syscall_arch.h @@ -24,7 +24,7 @@ static inline long __syscall0(long n) : "=&r"(r2), "=r"(r7) : "ir"(n) : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } static inline long __syscall1(long n, long a) @@ -37,7 +37,7 @@ static inline long __syscall1(long n, long a) : "=&r"(r2), "=r"(r7) : "ir"(n), "r"(r4) : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } static inline long __syscall2(long n, long a, long b) @@ -51,7 +51,7 @@ static inline long __syscall2(long n, long a, long b) : "=&r"(r2), "=r"(r7) : "ir"(n), "r"(r4), "r"(r5) : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } static inline long __syscall3(long n, long a, long b, long c) @@ -66,7 +66,7 @@ static inline long __syscall3(long n, long a, long b, long c) : "=&r"(r2), "=r"(r7) : "ir"(n), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } static inline long __syscall4(long n, long a, long b, long c, long d) @@ -81,7 +81,7 @@ static inline long __syscall4(long n, long a, long b, long c, long d) : "=&r"(r2), "+r"(r7) : "ir"(n), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } static inline long __syscall5(long n, long a, long b, long c, long d, long e) @@ -99,7 +99,7 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e) : "=&r"(r2), "+r"(r7), "+r"(r8) : "ir"(n), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST, "$9", "$10"); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) @@ -118,7 +118,7 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo : "=&r"(r2), "+r"(r7), "+r"(r8), "+r"(r9) : "ir"(n), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST, "$10"); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } static inline long __syscall7(long n, long a, long b, long c, long d, long e, long f, long g) @@ -138,7 +138,7 @@ static inline long __syscall7(long n, long a, long b, long c, long d, long e, lo : "=&r"(r2), "+r"(r7), "+r"(r8), "+r"(r9), "+r"(r10) : "ir"(n), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } #define VDSO_USEFUL diff --git a/arch/mips64/syscall_arch.h b/arch/mips64/syscall_arch.h index 8f6758d3..62492640 100644 --- a/arch/mips64/syscall_arch.h +++ b/arch/mips64/syscall_arch.h @@ -22,7 +22,7 @@ static inline long __syscall0(long n) : "=&r"(r2), "=r"(r7) : "ir"(n) : SYSCALL_CLOBBERLIST); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } static inline long __syscall1(long n, long a) @@ -35,7 +35,7 @@ static inline long __syscall1(long n, long a) : "=&r"(r2), "=r"(r7) : "ir"(n), "r"(r4) : SYSCALL_CLOBBERLIST); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } static inline long __syscall2(long n, long a, long b) @@ -50,7 +50,7 @@ static inline long __syscall2(long n, long a, long b) : "=&r"(r2), "=r"(r7) : "ir"(n), "r"(r4), "r"(r5) : SYSCALL_CLOBBERLIST); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } static inline long __syscall3(long n, long a, long b, long c) @@ -66,7 +66,7 @@ static inline long __syscall3(long n, long a, long b, long c) : "=&r"(r2), "=r"(r7) : "ir"(n), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } static inline long __syscall4(long n, long a, long b, long c, long d) @@ -82,7 +82,7 @@ static inline long __syscall4(long n, long a, long b, long c, long d) : "=&r"(r2), "+r"(r7) : "ir"(n), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } static inline long __syscall5(long n, long a, long b, long c, long d, long e) @@ -99,7 +99,7 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e) : "=&r"(r2), "+r"(r7) : "ir"(n), "r"(r4), "r"(r5), "r"(r6), "r"(r8) : SYSCALL_CLOBBERLIST); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) @@ -117,7 +117,7 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo : "=&r"(r2), "+r"(r7) : "ir"(n), "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9) : SYSCALL_CLOBBERLIST); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } #define VDSO_USEFUL diff --git a/arch/mipsn32/syscall_arch.h b/arch/mipsn32/syscall_arch.h index bc29e318..8b9e9ddd 100644 --- a/arch/mipsn32/syscall_arch.h +++ b/arch/mipsn32/syscall_arch.h @@ -22,7 +22,7 @@ static inline long __syscall0(long n) : "=&r"(r2), "=r"(r7) : "ir"(n) : SYSCALL_CLOBBERLIST); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } static inline long __syscall1(long n, long a) @@ -35,7 +35,7 @@ static inline long __syscall1(long n, long a) : "=&r"(r2), "=r"(r7) : "ir"(n), "r"(r4) : SYSCALL_CLOBBERLIST); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } static inline long __syscall2(long n, long a, long b) @@ -50,7 +50,7 @@ static inline long __syscall2(long n, long a, long b) : "=&r"(r2), "=r"(r7) : "ir"(n), "r"(r4), "r"(r5) : SYSCALL_CLOBBERLIST); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } static inline long __syscall3(long n, long a, long b, long c) @@ -66,7 +66,7 @@ static inline long __syscall3(long n, long a, long b, long c) : "=&r"(r2), "=r"(r7) : "ir"(n), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } static inline long __syscall4(long n, long a, long b, long c, long d) @@ -82,7 +82,7 @@ static inline long __syscall4(long n, long a, long b, long c, long d) : "=&r"(r2), "+r"(r7) : "ir"(n), "r"(r4), "r"(r5), "r"(r6) : SYSCALL_CLOBBERLIST); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } static inline long __syscall5(long n, long a, long b, long c, long d, long e) @@ -99,7 +99,7 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e) : "=&r"(r2), "+r"(r7) : "ir"(n), "r"(r4), "r"(r5), "r"(r6), "r"(r8) : SYSCALL_CLOBBERLIST); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) @@ -117,7 +117,7 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo : "=&r"(r2), "+r"(r7) : "ir"(n), "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9) : SYSCALL_CLOBBERLIST); - return r7 ? -r2 : r2; + return r7 && r2>0 ? -r2 : r2; } #define VDSO_USEFUL -- 2.21.0 --jRHKVT23PllUwdXP--