From patchwork Mon Oct 29 12:05:10 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 12562 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 2E9AB23FB6 for ; Mon, 29 Oct 2012 12:05:20 +0000 (UTC) Received: from mail-ie0-f180.google.com (mail-ie0-f180.google.com [209.85.223.180]) by fiordland.canonical.com (Postfix) with ESMTP id A04DBA1958D for ; Mon, 29 Oct 2012 12:05:19 +0000 (UTC) Received: by mail-ie0-f180.google.com with SMTP id e10so6163382iej.11 for ; Mon, 29 Oct 2012 05:05:19 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:from:to:cc :subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=+XLRGC3SC2yTILwytKmIr7u3QPHU9U3wmHae84RgkI8=; b=H70bJSND18HT0gVx+RiIaAGdJvrPnfVCLi8hPW/D6pvj/FCiLgJITOW3Cxe6wIHCUd EeWaKyGbW3dDLNOZcTLvXsCchztZYjG0HyU+FiEDud5IJoK3BTDz7BCZBGXga7HL30I/ 7DTK2leFCz/M76AjpICIQNeZdJc1mRnrZLa+olyxUjobbG7RO1y1oJpA+xm4OEQbcYqM 5pBuybXkxJupNFd2tRkeC9w5QUkJlGBQRTLlbTT4aXtwndqF3be8Qa94PIiJQ0p44vIQ yVwiYDfNcZRpL1RaAwf95hYgxKLxKLPv32de+ryLfv5iARIkmexNVM6pmNTfLGUlX1kg Wd5w== Received: by 10.50.152.137 with SMTP id uy9mr8986014igb.62.1351512319376; Mon, 29 Oct 2012 05:05:19 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.50.67.148 with SMTP id n20csp195090igt; Mon, 29 Oct 2012 05:05:17 -0700 (PDT) Received: by 10.216.220.29 with SMTP id n29mr15217090wep.137.1351512316916; Mon, 29 Oct 2012 05:05:16 -0700 (PDT) Received: from mnementh.archaic.org.uk (1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.1.0.0.b.8.0.1.0.0.2.ip6.arpa. [2001:8b0:1d0::1]) by mx.google.com with ESMTPS id k79si4952114wej.129.2012.10.29.05.05.16 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 29 Oct 2012 05:05:16 -0700 (PDT) Received-SPF: neutral (google.com: 2001:8b0:1d0::1 is neither permitted nor denied by best guess record for domain of pm215@archaic.org.uk) client-ip=2001:8b0:1d0::1; Authentication-Results: mx.google.com; spf=neutral (google.com: 2001:8b0:1d0::1 is neither permitted nor denied by best guess record for domain of pm215@archaic.org.uk) smtp.mail=pm215@archaic.org.uk Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.72) (envelope-from ) id 1TSo5f-0004yf-Fi; Mon, 29 Oct 2012 12:05:11 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, Meador Inge , Paul Brook , Blue Swirl Subject: [PATCH 2/3] target-m68k/m68k-semi: Handle get_user failure Date: Mon, 29 Oct 2012 12:05:10 +0000 Message-Id: <1351512311-19106-3-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1351512311-19106-1-git-send-email-peter.maydell@linaro.org> References: <1351512311-19106-1-git-send-email-peter.maydell@linaro.org> X-Gm-Message-State: ALoCoQnevcyc3nvjfO9N/Ta3G5LwtWa1ngqDKwcyVCB9NzST3yZ26PrpevcyTunbznJyXvWYJM0e Handle failure of get_user accessing the semihosting argument block, rather than simply ignoring the failures. Signed-off-by: Peter Maydell --- target-m68k/m68k-semi.c | 144 +++++++++++++++++++++++++++++++----------------- 1 file changed, 93 insertions(+), 51 deletions(-) diff --git a/target-m68k/m68k-semi.c b/target-m68k/m68k-semi.c index fed44ea..d569bf1 100644 --- a/target-m68k/m68k-semi.c +++ b/target-m68k/m68k-semi.c @@ -153,17 +153,21 @@ static void m68k_semi_cb(CPUM68KState *env, target_ulong ret, target_ulong err) put_user_u32(err, args + 4); } -#define ARG(n) \ -({ \ - target_ulong __arg; \ - /* FIXME - handle get_user() failure */ \ - get_user_ual(__arg, args + (n) * 4); \ - __arg; \ -}) -#define PARG(x) ((unsigned long)ARG(x)) +/* Read the input value from the argument block; fail the semihosting + * call if the memory read fails. + */ +#define GET_ARG(n) do { \ + if (get_user_ual(arg ## n, args + (n) * 4)) { \ + result = -1; \ + errno = EFAULT; \ + goto failed; \ + } \ +} while (0) + void do_m68k_semihosting(CPUM68KState *env, int nr) { uint32_t args; + target_ulong arg0, arg1, arg2, arg3; void *p; void *q; uint32_t len; @@ -175,27 +179,33 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) gdb_exit(env, env->dregs[0]); exit(env->dregs[0]); case HOSTED_OPEN: + GET_ARG(0); + GET_ARG(1); + GET_ARG(2); + GET_ARG(3); if (use_gdb_syscalls()) { - gdb_do_syscall(m68k_semi_cb, "open,%s,%x,%x", ARG(0), (int)ARG(1), - ARG(2), ARG(3)); + gdb_do_syscall(m68k_semi_cb, "open,%s,%x,%x", arg0, (int)arg1, + arg2, arg3); return; } else { - if (!(p = lock_user_string(ARG(0)))) { + p = lock_user_string(arg0); + if (!p) { /* FIXME - check error code? */ result = -1; } else { - result = open(p, translate_openflags(ARG(2)), ARG(3)); - unlock_user(p, ARG(0), 0); + result = open(p, translate_openflags(arg2), arg3); + unlock_user(p, arg0, 0); } } break; case HOSTED_CLOSE: { /* Ignore attempts to close stdin/out/err. */ - int fd = ARG(0); + GET_ARG(0); + int fd = arg0; if (fd > 2) { if (use_gdb_syscalls()) { - gdb_do_syscall(m68k_semi_cb, "close,%x", ARG(0)); + gdb_do_syscall(m68k_semi_cb, "close,%x", arg0); return; } else { result = close(fd); @@ -206,47 +216,59 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) break; } case HOSTED_READ: - len = ARG(2); + GET_ARG(0); + GET_ARG(1); + GET_ARG(2); + len = arg2; if (use_gdb_syscalls()) { gdb_do_syscall(m68k_semi_cb, "read,%x,%x,%x", - ARG(0), ARG(1), len); + arg0, arg1, len); return; } else { - if (!(p = lock_user(VERIFY_WRITE, ARG(1), len, 0))) { + p = lock_user(VERIFY_WRITE, arg1, len, 0); + if (!p) { /* FIXME - check error code? */ result = -1; } else { - result = read(ARG(0), p, len); - unlock_user(p, ARG(1), len); + result = read(arg0, p, len); + unlock_user(p, arg1, len); } } break; case HOSTED_WRITE: - len = ARG(2); + GET_ARG(0); + GET_ARG(1); + GET_ARG(2); + len = arg2; if (use_gdb_syscalls()) { gdb_do_syscall(m68k_semi_cb, "write,%x,%x,%x", - ARG(0), ARG(1), len); + arg0, arg1, len); return; } else { - if (!(p = lock_user(VERIFY_READ, ARG(1), len, 1))) { + p = lock_user(VERIFY_READ, arg1, len, 1); + if (!p) { /* FIXME - check error code? */ result = -1; } else { - result = write(ARG(0), p, len); - unlock_user(p, ARG(0), 0); + result = write(arg0, p, len); + unlock_user(p, arg0, 0); } } break; case HOSTED_LSEEK: { uint64_t off; - off = (uint32_t)ARG(2) | ((uint64_t)ARG(1) << 32); + GET_ARG(0); + GET_ARG(1); + GET_ARG(2); + GET_ARG(3); + off = (uint32_t)arg2 | ((uint64_t)arg1 << 32); if (use_gdb_syscalls()) { m68k_semi_is_fseek = 1; gdb_do_syscall(m68k_semi_cb, "fseek,%x,%lx,%x", - ARG(0), off, ARG(3)); + arg0, off, arg3); } else { - off = lseek(ARG(0), off, ARG(3)); + off = lseek(arg0, off, arg3); /* FIXME - handle put_user() failure */ put_user_u32(off >> 32, args); put_user_u32(off, args + 4); @@ -255,74 +277,89 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) return; } case HOSTED_RENAME: + GET_ARG(0); + GET_ARG(1); + GET_ARG(2); + GET_ARG(3); if (use_gdb_syscalls()) { gdb_do_syscall(m68k_semi_cb, "rename,%s,%s", - ARG(0), (int)ARG(1), ARG(2), (int)ARG(3)); + arg0, (int)arg1, arg2, (int)arg3); return; } else { - p = lock_user_string(ARG(0)); - q = lock_user_string(ARG(2)); + p = lock_user_string(arg0); + q = lock_user_string(arg2); if (!p || !q) { /* FIXME - check error code? */ result = -1; } else { result = rename(p, q); } - unlock_user(p, ARG(0), 0); - unlock_user(q, ARG(2), 0); + unlock_user(p, arg0, 0); + unlock_user(q, arg2, 0); } break; case HOSTED_UNLINK: + GET_ARG(0); + GET_ARG(1); if (use_gdb_syscalls()) { gdb_do_syscall(m68k_semi_cb, "unlink,%s", - ARG(0), (int)ARG(1)); + arg0, (int)arg1); return; } else { - if (!(p = lock_user_string(ARG(0)))) { + p = lock_user_string(arg0); + if (!p) { /* FIXME - check error code? */ result = -1; } else { result = unlink(p); - unlock_user(p, ARG(0), 0); + unlock_user(p, arg0, 0); } } break; case HOSTED_STAT: + GET_ARG(0); + GET_ARG(1); + GET_ARG(2); if (use_gdb_syscalls()) { gdb_do_syscall(m68k_semi_cb, "stat,%s,%x", - ARG(0), (int)ARG(1), ARG(2)); + arg0, (int)arg1, arg2); return; } else { struct stat s; - if (!(p = lock_user_string(ARG(0)))) { + p = lock_user_string(arg0); + if (!p) { /* FIXME - check error code? */ result = -1; } else { result = stat(p, &s); - unlock_user(p, ARG(0), 0); + unlock_user(p, arg0, 0); } if (result == 0) { - translate_stat(env, ARG(2), &s); + translate_stat(env, arg2, &s); } } break; case HOSTED_FSTAT: + GET_ARG(0); + GET_ARG(1); if (use_gdb_syscalls()) { gdb_do_syscall(m68k_semi_cb, "fstat,%x,%x", - ARG(0), ARG(1)); + arg0, arg1); return; } else { struct stat s; - result = fstat(ARG(0), &s); + result = fstat(arg0, &s); if (result == 0) { - translate_stat(env, ARG(1), &s); + translate_stat(env, arg1, &s); } } break; case HOSTED_GETTIMEOFDAY: + GET_ARG(0); + GET_ARG(1); if (use_gdb_syscalls()) { gdb_do_syscall(m68k_semi_cb, "gettimeofday,%x,%x", - ARG(0), ARG(1)); + arg0, arg1); return; } else { qemu_timeval tv; @@ -330,37 +367,41 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) result = qemu_gettimeofday(&tv); if (result != 0) { if (!(p = lock_user(VERIFY_WRITE, - ARG(0), sizeof(struct gdb_timeval), 0))) { + arg0, sizeof(struct gdb_timeval), 0))) { /* FIXME - check error code? */ result = -1; } else { p->tv_sec = cpu_to_be32(tv.tv_sec); p->tv_usec = cpu_to_be64(tv.tv_usec); - unlock_user(p, ARG(0), sizeof(struct gdb_timeval)); + unlock_user(p, arg0, sizeof(struct gdb_timeval)); } } } break; case HOSTED_ISATTY: + GET_ARG(0); if (use_gdb_syscalls()) { - gdb_do_syscall(m68k_semi_cb, "isatty,%x", ARG(0)); + gdb_do_syscall(m68k_semi_cb, "isatty,%x", arg0); return; } else { - result = isatty(ARG(0)); + result = isatty(arg0); } break; case HOSTED_SYSTEM: + GET_ARG(0); + GET_ARG(1); if (use_gdb_syscalls()) { gdb_do_syscall(m68k_semi_cb, "system,%s", - ARG(0), (int)ARG(1)); + arg0, (int)arg1); return; } else { - if (!(p = lock_user_string(ARG(0)))) { + p = lock_user_string(arg0); + if (!p) { /* FIXME - check error code? */ result = -1; } else { result = system(p); - unlock_user(p, ARG(0), 0); + unlock_user(p, arg0, 0); } } break; @@ -402,6 +443,7 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) cpu_abort(env, "Unsupported semihosting syscall %d\n", nr); result = 0; } +failed: /* FIXME - handle put_user() failure */ put_user_u32(result, args); put_user_u32(errno, args + 4);