From patchwork Tue Feb 22 13:02:26 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 191 Return-Path: Delivered-To: unknown Received: from imap.gmail.com (74.125.159.109) by localhost6.localdomain6 with IMAP4-SSL; 08 Jun 2011 14:40:46 -0000 Delivered-To: patches@linaro.org Received: by 10.224.19.208 with SMTP id c16cs233928qab; Tue, 22 Feb 2011 05:02:29 -0800 (PST) Received: by 10.227.133.81 with SMTP id e17mr2369011wbt.176.1298379749101; Tue, 22 Feb 2011 05:02:29 -0800 (PST) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk [81.2.115.146]) by mx.google.com with ESMTPS id b54si9312112wer.142.2011.02.22.05.02.28 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 22 Feb 2011 05:02:29 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 81.2.115.146 as permitted sender) client-ip=81.2.115.146; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 81.2.115.146 as permitted sender) smtp.mail=pm215@archaic.org.uk Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.72) (envelope-from ) id 1Prrso-0004oZ-7X; Tue, 22 Feb 2011 13:02:26 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, Eoghan Sherry Subject: [PATCH] linux-user: Fix large seeks by 32 bit guest on 64 bit host Date: Tue, 22 Feb 2011 13:02:26 +0000 Message-Id: <1298379746-18484-1-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.2.3 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 --- 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