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

Reply via email to