about summary refs log tree commit diff
path: root/arch
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2020-03-11 19:02:52 -0400
committerRich Felker <dalias@aerifal.cx>2020-03-14 21:23:37 -0400
commit5db475f0b987bfa7935a117aac81e14a98de34fb (patch)
tree3898bc9c526dfe56fe189c91493b9a7c7b1b082f /arch
parentdb86ec100dc9973946ebfc9cf0d91686e334731a (diff)
downloadmusl-5db475f0b987bfa7935a117aac81e14a98de34fb.tar.gz
musl-5db475f0b987bfa7935a117aac81e14a98de34fb.tar.xz
musl-5db475f0b987bfa7935a117aac81e14a98de34fb.zip
work around negated error code bug on some mips kernels
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.
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/syscall_arch.h16
-rw-r--r--arch/mips64/syscall_arch.h14
-rw-r--r--arch/mipsn32/syscall_arch.h14
3 files changed, 22 insertions, 22 deletions
diff --git a/arch/mips/syscall_arch.h b/arch/mips/syscall_arch.h
index 4286f00a..380a94b3 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), "0"(r2)
 		: 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), "0"(r2), "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), "0"(r2), "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), "0"(r2), "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), "0"(r2), "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), "0"(r2), "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), "0"(r2), "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), "0"(r2), "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 d34efdc0..ae6532fc 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), "0"(r2)
 		: 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), "0"(r2), "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), "0"(r2), "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), "0"(r2), "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), "0"(r2), "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), "0"(r2), "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), "0"(r2), "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 cbb4a055..c681905d 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), "0"(r2)
 		: 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), "0"(r2), "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), "0"(r2), "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), "0"(r2), "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), "0"(r2), "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), "0"(r2), "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), "0"(r2), "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