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