From 25748db301c242d36718c6708ffd2b67a456483a Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 7 Apr 2015 12:47:19 -0400 Subject: [PATCH] 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. --- arch/mips/syscall_arch.h | 9 ++++++--- 1 file 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