diff options
author | Chris Metcalf <cmetcalf@tilera.com> | 2013-03-04 11:19:09 -0500 |
---|---|---|
committer | Chris Metcalf <cmetcalf@tilera.com> | 2013-03-04 11:19:09 -0500 |
commit | 5a114b98661e3aaa0ac085eb931584dce3b0ef9b (patch) | |
tree | 375a9103da9b40c1213d3bf78ed25f99c0df8455 /arch/tile | |
parent | 6dbe51c251a327e012439c4772097a13df43c5b8 (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]
Diffstat (limited to 'arch/tile')
-rw-r--r-- | arch/tile/include/asm/compat.h | 3 | ||||
-rw-r--r-- | arch/tile/kernel/compat.c | 13 |
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, | |||
288 | long compat_sys_fallocate(int fd, int mode, | 288 | long 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); |
291 | long 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. */ |
293 | long _compat_sys_rt_sigreturn(void); | 296 | long _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 | */ | ||
84 | long 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 |