qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] linux-user: Fix large seeks by 32 bit guest on 64 bit host
@ 2011-02-22 13:02 Peter Maydell
  2011-03-06 18:07 ` Aurelien Jarno
  0 siblings, 1 reply; 2+ messages in thread
From: Peter Maydell @ 2011-02-22 13:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: Eoghan Sherry, patches

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>
---
 linux-user/syscall.c |   16 ++++++++++------
 1 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index cf8a4c3..23d7a63 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -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:
         {
+            int64_t res;
 #if !defined(__NR_llseek)
-            ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
-            if (put_user_s64(ret, arg4))
-                goto efault;
+            res = lseek(arg1, ((uint64_t)arg2 << 32) | arg3, arg5);
+            if (res == -1) {
+                ret = get_errno(res);
+            } else {
+                ret = 0;
+            }
 #else
-            int64_t res;
             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
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [Qemu-devel] [PATCH] linux-user: Fix large seeks by 32 bit guest on 64 bit host
  2011-02-22 13:02 [Qemu-devel] [PATCH] linux-user: Fix large seeks by 32 bit guest on 64 bit host Peter Maydell
@ 2011-03-06 18:07 ` Aurelien Jarno
  0 siblings, 0 replies; 2+ messages in thread
From: Aurelien Jarno @ 2011-03-06 18:07 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Eoghan Sherry, qemu-devel, patches

On Tue, Feb 22, 2011 at 01:02:26PM +0000, Peter Maydell wrote:
> 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>
> ---
>  linux-user/syscall.c |   16 ++++++++++------
>  1 files changed, 10 insertions(+), 6 deletions(-)

Thanks, applied.

> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index cf8a4c3..23d7a63 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -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:
>          {
> +            int64_t res;
>  #if !defined(__NR_llseek)
> -            ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
> -            if (put_user_s64(ret, arg4))
> -                goto efault;
> +            res = lseek(arg1, ((uint64_t)arg2 << 32) | arg3, arg5);
> +            if (res == -1) {
> +                ret = get_errno(res);
> +            } else {
> +                ret = 0;
> +            }
>  #else
> -            int64_t res;
>              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
> -- 
> 1.7.1
> 
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2011-03-06 18:07 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-02-22 13:02 [Qemu-devel] [PATCH] linux-user: Fix large seeks by 32 bit guest on 64 bit host Peter Maydell
2011-03-06 18:07 ` Aurelien Jarno

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).