linux-user: Fix large seeks by 32 bit guest on 64 bit host
When emulating a 32 bit Linux user-mode program on a 64 bit target we implement the llseek syscall in terms of lseek. Correct a bug which meant we were silently casting the result of host lseek() to a 32 bit integer as it passed through get_errno() and thus throwing away the top half. We also don't try to store the result back to userspace unless the seek succeeded; this matches the kernel behaviour. Thanks to Eoghan Sherry for identifying the problem and suggesting a solution. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
parent
26883c699e
commit
0c1592d935
@ -6127,16 +6127,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
#ifdef TARGET_NR__llseek /* Not on alpha */
|
||||
case TARGET_NR__llseek:
|
||||
{
|
||||
#if !defined(__NR_llseek)
|
||||
ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
|
||||
if (put_user_s64(ret, arg4))
|
||||
goto efault;
|
||||
#else
|
||||
int64_t res;
|
||||
#if !defined(__NR_llseek)
|
||||
res = lseek(arg1, ((uint64_t)arg2 << 32) | arg3, arg5);
|
||||
if (res == -1) {
|
||||
ret = get_errno(res);
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
#else
|
||||
ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
|
||||
if (put_user_s64(res, arg4))
|
||||
goto efault;
|
||||
#endif
|
||||
if ((ret == 0) && put_user_s64(res, arg4)) {
|
||||
goto efault;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user