qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] semihosting: fix various coverity issues
@ 2022-07-19 12:11 Peter Maydell
  2022-07-19 12:11 ` [PATCH 1/4] semihosting: Don't return negative values on qemu_semihosting_console_write() failure Peter Maydell
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Peter Maydell @ 2022-07-19 12:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: Alex Bennée

This patchset fixes a handful of bugs in the semihosting code
noticed by Coverity.

thanks
-- PMM

Peter Maydell (4):
  semihosting: Don't return negative values on
    qemu_semihosting_console_write() failure
  semihosting: Don't copy buffer after console_write()
  semihosting: Check for errors on SET_ARG()
  semihosting: Fix handling of buffer in TARGET_SYS_TMPNAM

 semihosting/arm-compat-semi.c | 29 ++++++++++++++++++++++++-----
 semihosting/console.c         |  3 ++-
 semihosting/syscalls.c        |  2 +-
 3 files changed, 27 insertions(+), 7 deletions(-)

-- 
2.25.1



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

* [PATCH 1/4] semihosting: Don't return negative values on qemu_semihosting_console_write() failure
  2022-07-19 12:11 [PATCH 0/4] semihosting: fix various coverity issues Peter Maydell
@ 2022-07-19 12:11 ` Peter Maydell
  2022-07-24 16:28   ` Richard Henderson
  2022-07-19 12:11 ` [PATCH 2/4] semihosting: Don't copy buffer after console_write() Peter Maydell
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Peter Maydell @ 2022-07-19 12:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: Alex Bennée

The documentation comment for qemu_semihosting_console_write() says
 * Returns: number of bytes written -- this should only ever be short
 * on some sort of i/o error.

and the callsites rely on this.  However, the implementation code
path which sends console output to a chardev doesn't honour this,
and will return negative values on error.  Bring it into line with
the other implementation codepaths and the documentation, so that
it returns 0 on error.

Spotted by Coverity, because console_write() passes the return value
to unlock_user(), which doesn't accept a negative length.

Resolves: Coverity CID 1490288
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
console_write() doesn't need to pass the length to unlock_user()
at all, as it happens -- see the next patch.
---
 semihosting/console.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/semihosting/console.c b/semihosting/console.c
index 5b1ec0a1c39..0f976fe8cb1 100644
--- a/semihosting/console.c
+++ b/semihosting/console.c
@@ -111,7 +111,8 @@ int qemu_semihosting_console_read(CPUState *cs, void *buf, int len)
 int qemu_semihosting_console_write(void *buf, int len)
 {
     if (console.chr) {
-        return qemu_chr_write_all(console.chr, (uint8_t *)buf, len);
+        int r = qemu_chr_write_all(console.chr, (uint8_t *)buf, len);
+        return r < 0 ? 0 : r;
     } else {
         return fwrite(buf, 1, len, stderr);
     }
-- 
2.25.1



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

* [PATCH 2/4] semihosting: Don't copy buffer after console_write()
  2022-07-19 12:11 [PATCH 0/4] semihosting: fix various coverity issues Peter Maydell
  2022-07-19 12:11 ` [PATCH 1/4] semihosting: Don't return negative values on qemu_semihosting_console_write() failure Peter Maydell
@ 2022-07-19 12:11 ` Peter Maydell
  2022-07-24 16:30   ` Richard Henderson
  2022-07-19 12:11 ` [PATCH 3/4] semihosting: Check for errors on SET_ARG() Peter Maydell
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Peter Maydell @ 2022-07-19 12:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: Alex Bennée

The console_write() semihosting function outputs guest data from a
buffer; it doesn't update that buffer.  It therefore doesn't need to
pass a length value to unlock_user(), but can pass 0, meaning "do not
copy any data back to the guest memory".

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 semihosting/syscalls.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/semihosting/syscalls.c b/semihosting/syscalls.c
index 4847f66c023..508a0ad88c6 100644
--- a/semihosting/syscalls.c
+++ b/semihosting/syscalls.c
@@ -627,7 +627,7 @@ static void console_write(CPUState *cs, gdb_syscall_complete_cb complete,
     }
     ret = qemu_semihosting_console_write(ptr, len);
     complete(cs, ret ? ret : -1, ret ? 0 : EIO);
-    unlock_user(ptr, buf, ret);
+    unlock_user(ptr, buf, 0);
 }
 
 static void console_fstat(CPUState *cs, gdb_syscall_complete_cb complete,
-- 
2.25.1



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

* [PATCH 3/4] semihosting: Check for errors on SET_ARG()
  2022-07-19 12:11 [PATCH 0/4] semihosting: fix various coverity issues Peter Maydell
  2022-07-19 12:11 ` [PATCH 1/4] semihosting: Don't return negative values on qemu_semihosting_console_write() failure Peter Maydell
  2022-07-19 12:11 ` [PATCH 2/4] semihosting: Don't copy buffer after console_write() Peter Maydell
@ 2022-07-19 12:11 ` Peter Maydell
  2022-07-24 16:35   ` Richard Henderson
  2022-07-19 12:11 ` [PATCH 4/4] semihosting: Fix handling of buffer in TARGET_SYS_TMPNAM Peter Maydell
  2022-07-25 12:28 ` [PATCH 0/4] semihosting: fix various coverity issues Alex Bennée
  4 siblings, 1 reply; 10+ messages in thread
From: Peter Maydell @ 2022-07-19 12:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: Alex Bennée

The SET_ARG() macro returns an error indication; we check this in the
TARGET_SYS_GET_CMDLINE case but not when we use it in implementing
TARGET_SYS_ELAPSED.  Check for and handle the errors via the do_fault
codepath, and update the comment documenting the SET_ARG() and
GET_ARG() macros to note how they handle memory access errors.

Resolves: Coverity CID 1490287
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 semihosting/arm-compat-semi.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c
index 1a1e2a69605..d12288fc806 100644
--- a/semihosting/arm-compat-semi.c
+++ b/semihosting/arm-compat-semi.c
@@ -171,6 +171,12 @@ static LayoutInfo common_semi_find_bases(CPUState *cs)
  * Read the input value from the argument block; fail the semihosting
  * call if the memory read fails. Eventually we could use a generic
  * CPUState helper function here.
+ * Note that GET_ARG() handles memory access errors by jumping to
+ * do_fault, so must be used as the first thing done in handling a
+ * semihosting call, to avoid accidentally leaking allocated resources.
+ * SET_ARG(), since it unavoidably happens late, instead returns an
+ * error indication (0 on success, non-0 for error) which the caller
+ * should check.
  */
 
 #define GET_ARG(n) do {                                 \
@@ -739,10 +745,14 @@ void do_common_semihosting(CPUState *cs)
     case TARGET_SYS_ELAPSED:
         elapsed = get_clock() - clock_start;
         if (sizeof(target_ulong) == 8) {
-            SET_ARG(0, elapsed);
+            if (SET_ARG(0, elapsed)) {
+                goto do_fault;
+            }
         } else {
-            SET_ARG(0, (uint32_t) elapsed);
-            SET_ARG(1, (uint32_t) (elapsed >> 32));
+            if (SET_ARG(0, (uint32_t) elapsed) ||
+                SET_ARG(1, (uint32_t) (elapsed >> 32))) {
+                goto do_fault;
+            }
         }
         common_semi_set_ret(cs, 0);
         break;
-- 
2.25.1



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

* [PATCH 4/4] semihosting: Fix handling of buffer in TARGET_SYS_TMPNAM
  2022-07-19 12:11 [PATCH 0/4] semihosting: fix various coverity issues Peter Maydell
                   ` (2 preceding siblings ...)
  2022-07-19 12:11 ` [PATCH 3/4] semihosting: Check for errors on SET_ARG() Peter Maydell
@ 2022-07-19 12:11 ` Peter Maydell
  2022-07-24 21:55   ` Richard Henderson
  2022-07-25 12:28 ` [PATCH 0/4] semihosting: fix various coverity issues Alex Bennée
  4 siblings, 1 reply; 10+ messages in thread
From: Peter Maydell @ 2022-07-19 12:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: Alex Bennée

The TARGET_SYS_TMPNAM implementation has two bugs spotted by
Coverity:
 * confusion about whether 'len' has the length of the string
   including or excluding the terminating NUL means we
   lock_user() len bytes of memory but memcpy() len + 1 bytes
 * In the error-exit cases we forget to free() the buffer
   that asprintf() returned to us

Resolves: Coverity CID 1490285, 1490289
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 semihosting/arm-compat-semi.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c
index d12288fc806..e741674238f 100644
--- a/semihosting/arm-compat-semi.c
+++ b/semihosting/arm-compat-semi.c
@@ -504,16 +504,25 @@ void do_common_semihosting(CPUState *cs)
         GET_ARG(1);
         GET_ARG(2);
         len = asprintf(&s, "/tmp/qemu-%x%02x", getpid(), (int)arg1 & 0xff);
+        if (len < 0) {
+            common_semi_set_ret(cs, -1);
+            break;
+        }
+
+        /* Allow for trailing NUL */
+        len++;
         /* Make sure there's enough space in the buffer */
-        if (len < 0 || len >= arg2) {
+        if (len > arg2) {
+            free(s);
             common_semi_set_ret(cs, -1);
             break;
         }
         p = lock_user(VERIFY_WRITE, arg0, len, 0);
         if (!p) {
+            free(s);
             goto do_fault;
         }
-        memcpy(p, s, len + 1);
+        memcpy(p, s, len);
         unlock_user(p, arg0, len);
         free(s);
         common_semi_set_ret(cs, 0);
-- 
2.25.1



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

* Re: [PATCH 1/4] semihosting: Don't return negative values on qemu_semihosting_console_write() failure
  2022-07-19 12:11 ` [PATCH 1/4] semihosting: Don't return negative values on qemu_semihosting_console_write() failure Peter Maydell
@ 2022-07-24 16:28   ` Richard Henderson
  0 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2022-07-24 16:28 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel; +Cc: Alex Bennée

On 7/19/22 17:41, Peter Maydell wrote:
> The documentation comment for qemu_semihosting_console_write() says
>   * Returns: number of bytes written -- this should only ever be short
>   * on some sort of i/o error.
> 
> and the callsites rely on this.  However, the implementation code
> path which sends console output to a chardev doesn't honour this,
> and will return negative values on error.  Bring it into line with
> the other implementation codepaths and the documentation, so that
> it returns 0 on error.
> 
> Spotted by Coverity, because console_write() passes the return value
> to unlock_user(), which doesn't accept a negative length.
> 
> Resolves: Coverity CID 1490288
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
> console_write() doesn't need to pass the length to unlock_user()
> at all, as it happens -- see the next patch.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH 2/4] semihosting: Don't copy buffer after console_write()
  2022-07-19 12:11 ` [PATCH 2/4] semihosting: Don't copy buffer after console_write() Peter Maydell
@ 2022-07-24 16:30   ` Richard Henderson
  0 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2022-07-24 16:30 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel; +Cc: Alex Bennée

On 7/19/22 17:41, Peter Maydell wrote:
> The console_write() semihosting function outputs guest data from a
> buffer; it doesn't update that buffer.  It therefore doesn't need to
> pass a length value to unlock_user(), but can pass 0, meaning "do not
> copy any data back to the guest memory".
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>   semihosting/syscalls.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~


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

* Re: [PATCH 3/4] semihosting: Check for errors on SET_ARG()
  2022-07-19 12:11 ` [PATCH 3/4] semihosting: Check for errors on SET_ARG() Peter Maydell
@ 2022-07-24 16:35   ` Richard Henderson
  0 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2022-07-24 16:35 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel; +Cc: Alex Bennée

On 7/19/22 17:41, Peter Maydell wrote:
> The SET_ARG() macro returns an error indication; we check this in the
> TARGET_SYS_GET_CMDLINE case but not when we use it in implementing
> TARGET_SYS_ELAPSED.  Check for and handle the errors via the do_fault
> codepath, and update the comment documenting the SET_ARG() and
> GET_ARG() macros to note how they handle memory access errors.
> 
> Resolves: Coverity CID 1490287
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH 4/4] semihosting: Fix handling of buffer in TARGET_SYS_TMPNAM
  2022-07-19 12:11 ` [PATCH 4/4] semihosting: Fix handling of buffer in TARGET_SYS_TMPNAM Peter Maydell
@ 2022-07-24 21:55   ` Richard Henderson
  0 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2022-07-24 21:55 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel; +Cc: Alex Bennée

On 7/19/22 17:41, Peter Maydell wrote:
> The TARGET_SYS_TMPNAM implementation has two bugs spotted by
> Coverity:
>   * confusion about whether 'len' has the length of the string
>     including or excluding the terminating NUL means we
>     lock_user() len bytes of memory but memcpy() len + 1 bytes
>   * In the error-exit cases we forget to free() the buffer
>     that asprintf() returned to us
> 
> Resolves: Coverity CID 1490285, 1490289
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
>   semihosting/arm-compat-semi.c | 13 +++++++++++--
>   1 file changed, 11 insertions(+), 2 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH 0/4] semihosting: fix various coverity issues
  2022-07-19 12:11 [PATCH 0/4] semihosting: fix various coverity issues Peter Maydell
                   ` (3 preceding siblings ...)
  2022-07-19 12:11 ` [PATCH 4/4] semihosting: Fix handling of buffer in TARGET_SYS_TMPNAM Peter Maydell
@ 2022-07-25 12:28 ` Alex Bennée
  4 siblings, 0 replies; 10+ messages in thread
From: Alex Bennée @ 2022-07-25 12:28 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> This patchset fixes a handful of bugs in the semihosting code
> noticed by Coverity.

Queued to testing/next, thanks.

-- 
Alex Bennée


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

end of thread, other threads:[~2022-07-25 12:43 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-07-19 12:11 [PATCH 0/4] semihosting: fix various coverity issues Peter Maydell
2022-07-19 12:11 ` [PATCH 1/4] semihosting: Don't return negative values on qemu_semihosting_console_write() failure Peter Maydell
2022-07-24 16:28   ` Richard Henderson
2022-07-19 12:11 ` [PATCH 2/4] semihosting: Don't copy buffer after console_write() Peter Maydell
2022-07-24 16:30   ` Richard Henderson
2022-07-19 12:11 ` [PATCH 3/4] semihosting: Check for errors on SET_ARG() Peter Maydell
2022-07-24 16:35   ` Richard Henderson
2022-07-19 12:11 ` [PATCH 4/4] semihosting: Fix handling of buffer in TARGET_SYS_TMPNAM Peter Maydell
2022-07-24 21:55   ` Richard Henderson
2022-07-25 12:28 ` [PATCH 0/4] semihosting: fix various coverity issues Alex Bennée

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).