about summary refs log tree commit diff
path: root/arch
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2015-04-07 12:47:19 -0400
committerRich Felker <dalias@aerifal.cx>2015-04-07 12:47:19 -0400
commit25748db301c242d36718c6708ffd2b67a456483a (patch)
tree811f546f5908b6826e65f6273b7ae16f6fdbcbbf /arch
parent05e0e301e3efbeb399b9f3d96fab63aac18e601a (diff)
downloadmusl-25748db301c242d36718c6708ffd2b67a456483a.tar.gz
musl-25748db301c242d36718c6708ffd2b67a456483a.tar.xz
musl-25748db301c242d36718c6708ffd2b67a456483a.zip
fix possible clobbering of syscall return values on mips
depending on the compiler's interpretation of __asm__ register names
for register class objects, it may be possible for the return value in
r2 to be clobbered by the function call to __stat_fix. I have not
observed any such breakage in normal builds and suspect it only
happens with -O0 or other unusual build options, but since there's an
ambiguity as to the semantics of this feature, it's best to use an
explicit temporary to avoid the issue.

based on reporting and patch by Eugene.
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/syscall_arch.h9
1 files changed, 6 insertions, 3 deletions
diff --git a/arch/mips/syscall_arch.h b/arch/mips/syscall_arch.h
index 0f89a1c1..69b8154f 100644
--- a/arch/mips/syscall_arch.h
+++ b/arch/mips/syscall_arch.h
@@ -60,8 +60,9 @@ static inline long __syscall2(long n, long a, long b)
 		: "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
 		  "$14", "$15", "$24", "$25", "hi", "lo", "memory");
 	if (r7) return -r2;
+	long ret = r2;
 	if (n == SYS_stat64 || n == SYS_fstat64 || n == SYS_lstat64) __stat_fix(b);
-	return r2;
+	return ret;
 }
 
 static inline long __syscall3(long n, long a, long b, long c)
@@ -78,8 +79,9 @@ static inline long __syscall3(long n, long a, long b, long c)
 		: "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
 		  "$14", "$15", "$24", "$25", "hi", "lo", "memory");
 	if (r7) return -r2;
+	long ret = r2;
 	if (n == SYS_stat64 || n == SYS_fstat64 || n == SYS_lstat64) __stat_fix(b);
-	return r2;
+	return ret;
 }
 
 static inline long __syscall4(long n, long a, long b, long c, long d)
@@ -96,9 +98,10 @@ static inline long __syscall4(long n, long a, long b, long c, long d)
 		: "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
 		  "$14", "$15", "$24", "$25", "hi", "lo", "memory");
 	if (r7) return -r2;
+	long ret = r2;
 	if (n == SYS_stat64 || n == SYS_fstat64 || n == SYS_lstat64) __stat_fix(b);
 	if (n == SYS_fstatat) __stat_fix(c);
-	return r2;
+	return ret;
 }
 
 #else