diff mbox series

[PULL,02/60] semihosting: Return failure from softmmu-uaccess.h functions

Message ID 20220628045403.508716-3-richard.henderson@linaro.org
State New
Headers show
Series [PULL,01/60] semihosting: Move exec/softmmu-semi.h to semihosting/softmmu-uaccess.h | expand

Commit Message

Richard Henderson June 28, 2022, 4:53 a.m. UTC
We were reporting unconditional success for these functions;
pass on any failure from cpu_memory_rw_debug.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/semihosting/softmmu-uaccess.h | 91 ++++++++++++---------------
 1 file changed, 39 insertions(+), 52 deletions(-)

Comments

Peter Maydell July 29, 2022, 2:31 p.m. UTC | #1
On Tue, 28 Jun 2022 at 05:54, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> We were reporting unconditional success for these functions;
> pass on any failure from cpu_memory_rw_debug.
>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

So, this commit makes us check the cpu_memory_rw_debug()
return value in the softmmu_lock_user() function; but Coverity
points out (CID 1490294) that we still aren't checking the
return value from when we call it in softmmu_unlock_user()...

What, if anything, should we do about that? In particular,
I think that for semihosting calls that write to guest memory,
if the guest passes us a pointer to read-only memory we're
not going to find out about that until unlock time.

thanks
-- PMM
Richard Henderson July 29, 2022, 3:53 p.m. UTC | #2
On 7/29/22 07:31, Peter Maydell wrote:
> On Tue, 28 Jun 2022 at 05:54, Richard Henderson
> <richard.henderson@linaro.org> wrote:
>>
>> We were reporting unconditional success for these functions;
>> pass on any failure from cpu_memory_rw_debug.
>>
>> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> 
> So, this commit makes us check the cpu_memory_rw_debug()
> return value in the softmmu_lock_user() function; but Coverity
> points out (CID 1490294) that we still aren't checking the
> return value from when we call it in softmmu_unlock_user()...
> 
> What, if anything, should we do about that? In particular,
> I think that for semihosting calls that write to guest memory,
> if the guest passes us a pointer to read-only memory we're
> not going to find out about that until unlock time.

Not even then, because address_space_write_rom will in fact write to rom, nevermind 
virtual page permissions.  Moreover, there are no failure conditions from 
address_space_write_rom.  It skips non-{ram,rom} and always returns OK.

It's probable that we should be using cpu_memory_rw_debug at all, but should be using a 
higher-level interface, something that (1) checks the virtual page permissions and (2) 
probably rejects semihosting to mmio.

But in the short term, I think we can just ignore the warning.


r~
Philippe Mathieu-Daudé Jan. 29, 2024, 9:49 a.m. UTC | #3
On 28/6/22 06:53, Richard Henderson wrote:
> We were reporting unconditional success for these functions;
> pass on any failure from cpu_memory_rw_debug.
> 
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   include/semihosting/softmmu-uaccess.h | 91 ++++++++++++---------------
>   1 file changed, 39 insertions(+), 52 deletions(-)
> 
> diff --git a/include/semihosting/softmmu-uaccess.h b/include/semihosting/softmmu-uaccess.h
> index e69e3c8548..5246a91570 100644
> --- a/include/semihosting/softmmu-uaccess.h
> +++ b/include/semihosting/softmmu-uaccess.h
> @@ -12,82 +12,69 @@
>   
>   #include "cpu.h"
>   
> -static inline uint64_t softmmu_tget64(CPUArchState *env, target_ulong addr)
> -{
> -    uint64_t val;
> +#define get_user_u64(val, addr)                                         \

These macros match their user emulation equivalent, at the price
of loosing the 'env' argument, still used. This confuses meta
transformation tools such Coccinelle spatch. Not a big deal, just FTR.

> +    ({ uint64_t val_ = 0;                                               \
> +       int ret_ = cpu_memory_rw_debug(env_cpu(env), (addr),             \

                                               ^^^

> +                                      &val_, sizeof(val_), 0);          \
> +       (val) = tswap64(val_); ret_; })
>   
> -    cpu_memory_rw_debug(env_cpu(env), addr, (uint8_t *)&val, 8, 0);
> -    return tswap64(val);
> -}
diff mbox series

Patch

diff --git a/include/semihosting/softmmu-uaccess.h b/include/semihosting/softmmu-uaccess.h
index e69e3c8548..5246a91570 100644
--- a/include/semihosting/softmmu-uaccess.h
+++ b/include/semihosting/softmmu-uaccess.h
@@ -12,82 +12,69 @@ 
 
 #include "cpu.h"
 
-static inline uint64_t softmmu_tget64(CPUArchState *env, target_ulong addr)
-{
-    uint64_t val;
+#define get_user_u64(val, addr)                                         \
+    ({ uint64_t val_ = 0;                                               \
+       int ret_ = cpu_memory_rw_debug(env_cpu(env), (addr),             \
+                                      &val_, sizeof(val_), 0);          \
+       (val) = tswap64(val_); ret_; })
 
-    cpu_memory_rw_debug(env_cpu(env), addr, (uint8_t *)&val, 8, 0);
-    return tswap64(val);
-}
+#define get_user_u32(val, addr)                                         \
+    ({ uint32_t val_ = 0;                                               \
+       int ret_ = cpu_memory_rw_debug(env_cpu(env), (addr),             \
+                                      &val_, sizeof(val_), 0);          \
+       (val) = tswap32(val_); ret_; })
 
-static inline uint32_t softmmu_tget32(CPUArchState *env, target_ulong addr)
-{
-    uint32_t val;
+#define get_user_u8(val, addr)                                          \
+    ({ uint8_t val_ = 0;                                                \
+       int ret_ = cpu_memory_rw_debug(env_cpu(env), (addr),             \
+                                      &val_, sizeof(val_), 0);          \
+       (val) = val_; ret_; })
 
-    cpu_memory_rw_debug(env_cpu(env), addr, (uint8_t *)&val, 4, 0);
-    return tswap32(val);
-}
-
-static inline uint32_t softmmu_tget8(CPUArchState *env, target_ulong addr)
-{
-    uint8_t val;
-
-    cpu_memory_rw_debug(env_cpu(env), addr, &val, 1, 0);
-    return val;
-}
-
-#define get_user_u64(arg, p) ({ arg = softmmu_tget64(env, p); 0; })
-#define get_user_u32(arg, p) ({ arg = softmmu_tget32(env, p) ; 0; })
-#define get_user_u8(arg, p) ({ arg = softmmu_tget8(env, p) ; 0; })
 #define get_user_ual(arg, p) get_user_u32(arg, p)
 
-static inline void softmmu_tput64(CPUArchState *env,
-                                  target_ulong addr, uint64_t val)
-{
-    val = tswap64(val);
-    cpu_memory_rw_debug(env_cpu(env), addr, (uint8_t *)&val, 8, 1);
-}
+#define put_user_u64(val, addr)                                         \
+    ({ uint64_t val_ = tswap64(val);                                    \
+       cpu_memory_rw_debug(env_cpu(env), (addr), &val_, sizeof(val_), 1); })
+
+#define put_user_u32(val, addr)                                         \
+    ({ uint32_t val_ = tswap32(val);                                    \
+       cpu_memory_rw_debug(env_cpu(env), (addr), &val_, sizeof(val_), 1); })
 
-static inline void softmmu_tput32(CPUArchState *env,
-                                  target_ulong addr, uint32_t val)
-{
-    val = tswap32(val);
-    cpu_memory_rw_debug(env_cpu(env), addr, (uint8_t *)&val, 4, 1);
-}
-#define put_user_u64(arg, p) ({ softmmu_tput64(env, p, arg) ; 0; })
-#define put_user_u32(arg, p) ({ softmmu_tput32(env, p, arg) ; 0; })
 #define put_user_ual(arg, p) put_user_u32(arg, p)
 
-static void *softmmu_lock_user(CPUArchState *env,
-                               target_ulong addr, target_ulong len, int copy)
+static void *softmmu_lock_user(CPUArchState *env, target_ulong addr,
+                               target_ulong len, bool copy)
 {
-    uint8_t *p;
-    /* TODO: Make this something that isn't fixed size.  */
-    p = malloc(len);
+    void *p = malloc(len);
     if (p && copy) {
-        cpu_memory_rw_debug(env_cpu(env), addr, p, len, 0);
+        if (cpu_memory_rw_debug(env_cpu(env), addr, p, len, 0)) {
+            free(p);
+            p = NULL;
+        }
     }
     return p;
 }
 #define lock_user(type, p, len, copy) softmmu_lock_user(env, p, len, copy)
+
 static char *softmmu_lock_user_string(CPUArchState *env, target_ulong addr)
 {
-    char *p;
-    char *s;
-    uint8_t c;
     /* TODO: Make this something that isn't fixed size.  */
-    s = p = malloc(1024);
+    char *s = malloc(1024);
+    size_t len = 0;
+
     if (!s) {
         return NULL;
     }
     do {
-        cpu_memory_rw_debug(env_cpu(env), addr, &c, 1, 0);
-        addr++;
-        *(p++) = c;
-    } while (c);
+        if (cpu_memory_rw_debug(env_cpu(env), addr++, s + len, 1, 0)) {
+            free(s);
+            return NULL;
+        }
+    } while (s[len++]);
     return s;
 }
 #define lock_user_string(p) softmmu_lock_user_string(env, p)
+
 static void softmmu_unlock_user(CPUArchState *env, void *p, target_ulong addr,
                                 target_ulong len)
 {