HEX_SYS_OPEN copied guest bytes into a fixed-size buffer until it found a NUL.
A missing terminator could overrun that buffer, so use lock_user_string()
instead.
Fixes: 7711fdba88b ("target/hexagon: add main arch-specific semihosting
operations")
Link:
https://lore.kernel.org/all/cafeaca9mos6vfhf2uhz8z4cdvab+7dy6hjb2emyz2alse-t...@mail.gmail.com/
Suggested-by: Peter Maydell <[email protected]>
Signed-off-by: Brian Cain <[email protected]>
---
target/hexagon/hexswi.c | 27 +++++++++------------------
1 file changed, 9 insertions(+), 18 deletions(-)
diff --git a/target/hexagon/hexswi.c b/target/hexagon/hexswi.c
index 75f0a9cc520..cb6a061af16 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 */
@@ -461,31 +462,14 @@ static void sim_handle_trap0(CPUHexagonState *env)
case HEX_SYS_OPEN:
{
- char filename[BUFSIZ];
+ char *filename;
target_ulong physical_filename_addr;
unsigned int filemode;
- int 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 (length >= BUFSIZ) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: filename too large (%d)\n",
- __func__, length);
- semi_cb(cs, -1, ENAMETOOLONG);
- break;
- }
-
- do {
- hexagon_read_memory(env, physical_filename_addr + i, 1,
- &filename[i], retaddr);
- i++;
- } while (filename[i - 1]);
/* convert ARM ANGEL filemode into host filemode */
if (filemode < ARRAY_SIZE(angel_to_host_filemode_table)) {
@@ -498,6 +482,12 @@ static void sim_handle_trap0(CPUHexagonState *env)
break;
}
+ filename = lock_user_string(physical_filename_addr);
+ if (!filename) {
+ semi_cb(cs, -1, EFAULT);
+ break;
+ }
+
if (strcmp(filename, ":tt") == 0 &&
qemu_semihosting_console_has_chardev()) {
ret = alloc_guestfd();
@@ -513,6 +503,7 @@ static void sim_handle_trap0(CPUHexagonState *env)
ret = guestfd;
}
}
+ unlock_user(filename, physical_filename_addr, 0);
semi_cb(cs, ret, err);
}
break;
--
2.34.1