Link: 
https://lore.kernel.org/qemu-devel/cafeaca9el10xppx_0yd-q6ycwwp9-iwcyg8x0s1yqhkb-xq...@mail.gmail.com/
Suggested-by: Peter Maydell <[email protected]>
Signed-off-by: Brian Cain <[email protected]>
---
 target/hexagon/cpu_helper.h |  2 -
 target/hexagon/cpu_helper.c | 48 ++------------------
 target/hexagon/hexswi.c     | 90 ++++++++++++++++++++++++-------------
 3 files changed, 64 insertions(+), 76 deletions(-)

diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
index 8b1fb98a51a..b261b9177bc 100644
--- a/target/hexagon/cpu_helper.h
+++ b/target/hexagon/cpu_helper.h
@@ -7,8 +7,6 @@
 #ifndef HEXAGON_CPU_HELPER_H
 #define HEXAGON_CPU_HELPER_H
 
-void hexagon_read_memory(CPUHexagonState *env, target_ulong vaddr, int size,
-                         void *retptr, uintptr_t retaddr);
 void hexagon_write_memory(CPUHexagonState *env, target_ulong vaddr,
                           int size, uint64_t data, uintptr_t retaddr);
 void hexagon_peek_memory_range(CPUHexagonState *env, uint32_t start_addr,
diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
index 6dc06401ad5..c66ad88108d 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -28,48 +28,6 @@
 
 #ifndef CONFIG_USER_ONLY
 
-static bool hexagon_read_memory_small(CPUHexagonState *env, target_ulong addr,
-                                      int byte_count, uint64_t *data,
-                                      int mmu_idx, uintptr_t retaddr)
- {
-    /* handle small sizes */
-    switch (byte_count) {
-    case 1:
-        *data = cpu_ldub_mmuidx_ra(env, addr, mmu_idx, retaddr);
-        return true;
-
-    case 2:
-        *data = cpu_lduw_le_mmuidx_ra(env, addr, mmu_idx, retaddr);
-        return true;
-
-    case 4:
-        *data = cpu_ldl_le_mmuidx_ra(env, addr, mmu_idx, retaddr);
-        return true;
-
-    case 8:
-        *data = cpu_ldq_le_mmuidx_ra(env, addr, mmu_idx, retaddr);
-        return true;
-
-    default:
-        /* larger request, handle elsewhere */
-        return false;
-    }
-}
-
-void hexagon_read_memory(CPUHexagonState *env, target_ulong vaddr, int size,
-                         void *retptr, uintptr_t retaddr)
-{
-    BQL_LOCK_GUARD();
-    CPUState *cs = env_cpu(env);
-    unsigned mmu_idx = cpu_mmu_index(cs, false);
-    uint64_t data;
-    if (hexagon_read_memory_small(env, vaddr, size, &data, mmu_idx, retaddr)) {
-        stn_he_p(retptr, size, data);
-    } else {
-        cpu_abort(cs, "%s: ERROR: bad size = %d!\n", __func__, size);
-    }
-}
-
 static bool hexagon_write_memory_small(CPUHexagonState *env, target_ulong addr,
                                        int byte_count, uint64_t data,
                                        int mmu_idx, uintptr_t retaddr)
@@ -117,11 +75,13 @@ static inline uint32_t page_start(uint32_t addr)
 void hexagon_peek_memory_range(CPUHexagonState *env, uint32_t start_addr,
                                uint32_t length, uintptr_t retaddr)
 {
-    unsigned int warm;
+    CPUState *cs = env_cpu(env);
+    unsigned int mmu_idx = cpu_mmu_index(cs, false);
     uint32_t first = page_start(start_addr);
     uint32_t last = page_start(start_addr + length - 1);
+
     for (uint32_t page = first; page <= last; page += TARGET_PAGE_SIZE) {
-        hexagon_read_memory(env, page, 1, &warm, retaddr);
+        cpu_ldub_mmuidx_ra(env, page, mmu_idx, retaddr);
     }
 }
 
diff --git a/target/hexagon/hexswi.c b/target/hexagon/hexswi.c
index e7362b56650..bc809594335 100644
--- a/target/hexagon/hexswi.c
+++ b/target/hexagon/hexswi.c
@@ -28,6 +28,7 @@
 #include "semihosting/console.h"
 #include "semihosting/syscalls.h"
 #include "semihosting/guestfd.h"
+#include "semihosting/uaccess.h"
 #include "system/runstate.h"
 
 /* non-arm-compatible semihosting calls */
@@ -168,14 +169,18 @@ static void init_semihosting_guestfds(void)
     }
 }
 
-static void do_preload(CPUHexagonState *env, target_ulong swi_info, bool load)
+static bool do_preload(CPUHexagonState *env, target_ulong swi_info)
 {
+    CPUState *cs = env_cpu(env);
     uint32_t addr, count;
     uintptr_t retaddr = 0;
 
-    hexagon_read_memory(env, swi_info + 4, 4, &addr, retaddr);
-    hexagon_read_memory(env, swi_info + 8, 4, &count, retaddr);
+    if (get_user_u32(addr, swi_info + 4) ||
+        get_user_u32(count, swi_info + 8)) {
+        return false;
+    }
     hexagon_peek_memory_range(env, addr, count, retaddr);
+    return true;
 }
 
 /* Hexagon semihosting errno values */
@@ -429,7 +434,10 @@ static void sim_handle_trap0(CPUHexagonState *env)
              * the input address. The contents of that buffer will be
              * directed to the SWI interface.
              */
-            do_preload(env, swi_info, (what_swi == HEX_SYS_WRITE));
+            if (!do_preload(env, swi_info)) {
+                semi_cb(cs, -1, EFAULT);
+                return;
+            }
         }
         /*
          * ARM-compat semihosting SWI numbers are all <= 0x31.
@@ -464,26 +472,29 @@ static void sim_handle_trap0(CPUHexagonState *env)
         char filename[BUFSIZ];
         target_ulong physical_filename_addr;
         unsigned int filemode;
-        int length;
+        uint32_t length;
         int real_openmode;
         int ret, err = 0;
         int i = 0;
 
-        hexagon_read_memory(env, swi_info, 4, &physical_filename_addr, 
retaddr);
-        hexagon_read_memory(env, swi_info + 4, 4, &filemode, retaddr);
-        hexagon_read_memory(env, swi_info + 8, 4, &length, retaddr);
+        if (get_user_u32(physical_filename_addr, swi_info) ||
+            get_user_u32(filemode, swi_info + 4) ||
+            get_user_u32(length, swi_info + 8)) {
+            goto do_fault;
+        }
 
         if (length >= BUFSIZ) {
             qemu_log_mask(LOG_GUEST_ERROR,
-                          "%s: filename too large (%d)\n",
+                          "%s: filename too large (%" PRIu32 ")\n",
                           __func__, length);
             semi_cb(cs, -1, ENAMETOOLONG);
             break;
         }
 
         do {
-            hexagon_read_memory(env, physical_filename_addr + i, 1,
-                                &filename[i], retaddr);
+            if (get_user_u8(filename[i], physical_filename_addr + i)) {
+                goto do_fault;
+            }
             i++;
         } while (filename[i - 1]);
 
@@ -513,6 +524,7 @@ static void sim_handle_trap0(CPUHexagonState *env)
                 ret = guestfd;
             }
         }
+        unlock_user(filename, physical_filename_addr, 0);
         semi_cb(cs, ret, err);
     }
     break;
@@ -531,7 +543,9 @@ static void sim_handle_trap0(CPUHexagonState *env)
     case HEX_SYS_ISTTY:
     {
         int fd;
-        hexagon_read_memory(env, swi_info, 4, &fd, retaddr);
+        if (get_user_u32(fd, swi_info)) {
+            goto do_fault;
+        }
         semi_cb(cs, isatty(fd), 0);
     }
     break;
@@ -540,8 +554,10 @@ static void sim_handle_trap0(CPUHexagonState *env)
     {
         int fd;
         target_ulong off;
-        hexagon_read_memory(env, swi_info, 4, &fd, retaddr);
-        hexagon_read_memory(env, swi_info + 4, 4, &off, retaddr);
+        if (get_user_u32(fd, swi_info) ||
+            get_user_u32(off, swi_info + 4)) {
+            goto do_fault;
+        }
         semihost_sys_lseek(env_cpu(env), common_semi_ftell_cb, fd, off,
                           GDB_SEEK_SET);
     }
@@ -556,13 +572,17 @@ static void sim_handle_trap0(CPUHexagonState *env)
         char filename[BUFSIZ];
         target_ulong physical_filename_addr;
         target_ulong statBufferAddr;
-        hexagon_read_memory(env, swi_info, 4, &physical_filename_addr, 
retaddr);
+        if (get_user_u32(physical_filename_addr, swi_info) ||
+            get_user_u32(statBufferAddr, swi_info + 4)) {
+            goto do_fault;
+        }
 
         if (what_swi == HEX_SYS_STAT) {
             int i = 0;
             do {
-                hexagon_read_memory(env, physical_filename_addr + i, 1,
-                                    &filename[i], retaddr);
+                if (get_user_u8(filename[i], physical_filename_addr + i)) {
+                    goto do_fault;
+                }
                 i++;
             } while ((i < BUFSIZ) && filename[i - 1]);
             rc = stat(filename, &st_buf);
@@ -590,8 +610,6 @@ static void sim_handle_trap0(CPUHexagonState *env)
             sys_stat.mtime = cpu_to_le32(st_buf.st_mtime);
             sys_stat.ctime = cpu_to_le32(st_buf.st_ctime);
         }
-        hexagon_read_memory(env, swi_info + 4, 4, &statBufferAddr, retaddr);
-
         for (int i = 0; i < sizeof(sys_stat); i++) {
             hexagon_write_memory(env, statBufferAddr + i, 1, st_bufptr[i],
                                  retaddr);
@@ -604,8 +622,10 @@ static void sim_handle_trap0(CPUHexagonState *env)
     {
         int fd;
         off_t size_limit;
-        hexagon_read_memory(env, swi_info, 4, &fd, retaddr);
-        hexagon_read_memory(env, swi_info + 4, 8, &size_limit, retaddr);
+        if (get_user_u32(fd, swi_info) ||
+            get_user_u64(size_limit, swi_info + 4)) {
+            goto do_fault;
+        }
         semihost_sys_ftruncate(cs, semi_cb, fd, size_limit);
     }
     break;
@@ -619,16 +639,17 @@ static void sim_handle_trap0(CPUHexagonState *env)
 
         int i = 0;
 
-        hexagon_read_memory(env, swi_info, 4, &FileNameAddr, retaddr);
+        if (get_user_u32(FileNameAddr, swi_info) ||
+            get_user_u32(BufferMode, swi_info + 4)) {
+            goto do_fault;
+        }
         do {
-            hexagon_read_memory(env, FileNameAddr + i, 1, &filename[i],
-                                retaddr);
+            if (get_user_u8(filename[i], FileNameAddr + i)) {
+                goto do_fault;
+            }
             i++;
         } while ((i < BUFSIZ) && (filename[i - 1]));
         filename[i] = 0;
-
-        hexagon_read_memory(env, swi_info + 4, 4, &BufferMode, retaddr);
-
         rc = access(filename, BufferMode);
         semi_cb(cs, rc,  rc == 0 ? 0 : errno);
     }
@@ -641,8 +662,10 @@ static void sim_handle_trap0(CPUHexagonState *env)
         uint32_t BufferSize;
         uint32_t rc = 0, err = 0;
 
-        hexagon_read_memory(env, swi_info, 4, &BufferAddr, retaddr);
-        hexagon_read_memory(env, swi_info + 4, 4, &BufferSize, retaddr);
+        if (get_user_u32(BufferAddr, swi_info) ||
+            get_user_u32(BufferSize, swi_info + 4)) {
+            goto do_fault;
+        }
 
         if (!getcwd(cwdPtr, PATH_MAX)) {
             err = errno;
@@ -676,7 +699,9 @@ static void sim_handle_trap0(CPUHexagonState *env)
     case HEX_SYS_FTELL:
     {
         int fd;
-        hexagon_read_memory(env, swi_info, 4, &fd, retaddr);
+        if (get_user_u32(fd, swi_info)) {
+            goto do_fault;
+        }
         semihost_sys_lseek(cs, common_semi_ftell_cb, fd, 0, GDB_SEEK_CUR);
     }
     break;
@@ -720,6 +745,11 @@ static void sim_handle_trap0(CPUHexagonState *env)
                       "unknown swi request: 0x%" PRIx32 "\n",
                       (uint32_t)what_swi);
         semi_cb(cs, -1, ENOSYS);
+        break;
+
+    do_fault:
+        semi_cb(cs, -1, EFAULT);
+        break;
     }
 }
 
-- 
2.34.1

Reply via email to