work around negated error code bug on some mips kernels
authorRich Felker <dalias@aerifal.cx>
Wed, 11 Mar 2020 23:02:52 +0000 (19:02 -0400)
committerRich Felker <dalias@aerifal.cx>
Sun, 15 Mar 2020 01:23:37 +0000 (21:23 -0400)
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
arch/mips64/syscall_arch.h
arch/mipsn32/syscall_arch.h

index 4286f00a1d6fb8defe810afe9e19b9355d961638..380a94b366512c128101fc97ffbeec24b20052a9 100644 (file)
@@ -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
index d34efdc0d1778f99135c0e4ec5577b8c740d4f01..ae6532fcd4f2c478504b36822dc1537f58256d72 100644 (file)
@@ -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
index cbb4a05532c441c372138c512acad3693520644c..c681905d0f2b441edb71a0d63e39ef8f0262a907 100644 (file)
@@ -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