aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2013-03-04 11:19:09 -0500
committerChris Metcalf <cmetcalf@tilera.com>2013-03-04 11:19:09 -0500
commit5a114b98661e3aaa0ac085eb931584dce3b0ef9b (patch)
tree375a9103da9b40c1213d3bf78ed25f99c0df8455
parent6dbe51c251a327e012439c4772097a13df43c5b8 (diff)
tile: work around bug in the generic sys_llseek
sys_llseek should specify the high and low 32-bit seek values as "unsigned int" but instead it specifies "unsigned long". Since compat syscall arguments are always sign-extended on tile, this means that a seek value of 0xffffffff will be incorrectly interpreted as a value of -1ULL. To avoid the risk of breaking binary compatibility on architectures that already use sys_llseek this way, we follow the same path as MIPS and provide a wrapper override. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com> Cc: stable@kernel.org [v3.6 onwards]
-rw-r--r--arch/tile/include/asm/compat.h3
-rw-r--r--arch/tile/kernel/compat.c13
2 files changed, 16 insertions, 0 deletions
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h
index 001d418a8957..78f1f2ded86c 100644
--- a/arch/tile/include/asm/compat.h
+++ b/arch/tile/include/asm/compat.h
@@ -288,6 +288,9 @@ long compat_sys_sync_file_range2(int fd, unsigned int flags,
288long compat_sys_fallocate(int fd, int mode, 288long compat_sys_fallocate(int fd, int mode,
289 u32 offset_lo, u32 offset_hi, 289 u32 offset_lo, u32 offset_hi,
290 u32 len_lo, u32 len_hi); 290 u32 len_lo, u32 len_hi);
291long compat_sys_llseek(unsigned int fd, unsigned int offset_high,
292 unsigned int offset_low, loff_t __user * result,
293 unsigned int origin);
291 294
292/* Assembly trampoline to avoid clobbering r0. */ 295/* Assembly trampoline to avoid clobbering r0. */
293long _compat_sys_rt_sigreturn(void); 296long _compat_sys_rt_sigreturn(void);
diff --git a/arch/tile/kernel/compat.c b/arch/tile/kernel/compat.c
index 7f72401b4f45..69034e215742 100644
--- a/arch/tile/kernel/compat.c
+++ b/arch/tile/kernel/compat.c
@@ -76,6 +76,18 @@ long compat_sys_fallocate(int fd, int mode,
76 ((loff_t)len_hi << 32) | len_lo); 76 ((loff_t)len_hi << 32) | len_lo);
77} 77}
78 78
79/*
80 * Avoid bug in generic sys_llseek() that specifies offset_high and
81 * offset_low as "unsigned long", thus making it possible to pass
82 * a sign-extended high 32 bits in offset_low.
83 */
84long compat_sys_llseek(unsigned int fd, unsigned int offset_high,
85 unsigned int offset_low, loff_t __user * result,
86 unsigned int origin)
87{
88 return sys_llseek(fd, offset_high, offset_low, result, origin);
89}
90
79/* Provide the compat syscall number to call mapping. */ 91/* Provide the compat syscall number to call mapping. */
80#undef __SYSCALL 92#undef __SYSCALL
81#define __SYSCALL(nr, call) [nr] = (call), 93#define __SYSCALL(nr, call) [nr] = (call),
@@ -83,6 +95,7 @@ long compat_sys_fallocate(int fd, int mode,
83/* See comments in sys.c */ 95/* See comments in sys.c */
84#define compat_sys_fadvise64_64 sys32_fadvise64_64 96#define compat_sys_fadvise64_64 sys32_fadvise64_64
85#define compat_sys_readahead sys32_readahead 97#define compat_sys_readahead sys32_readahead
98#define sys_llseek compat_sys_llseek
86 99
87/* Call the assembly trampolines where necessary. */ 100/* Call the assembly trampolines where necessary. */
88#define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn 101#define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn