diff mbox series

[PULL,06/10] bsd-user: Allocate guest virtual address space

Message ID 20230731210211.137353-7-richard.henderson@linaro.org
State Accepted
Commit 28b61d49ac80bac8ef74aff0b75058bdd0b2f108
Headers show
Series [PULL,01/10] util/interval-tree: Use qatomic_read for left/right while searching | expand

Commit Message

Richard Henderson July 31, 2023, 9:02 p.m. UTC
With reserved_va, mmap.c expects to have pre-allocated host address
space for the entire guest address space.  When combined with the -B
command-line option, ensure that the chosen address does not overlap
anything else.  Ensure that mmap_next_start is within reserved_va,
as we use it within mmap.c without checking.

Reviewed by: Warner Losh <imp@bsdimp.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20230727161148.444988-1-richard.henderson@linaro.org>
---
 bsd-user/main.c | 48 +++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 43 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/bsd-user/main.c b/bsd-user/main.c
index b597328118..381bb18df8 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -473,10 +473,6 @@  int main(int argc, char **argv)
     target_environ = envlist_to_environ(envlist, NULL);
     envlist_free(envlist);
 
-    if (reserved_va) {
-        mmap_next_start = reserved_va + 1;
-    }
-
     {
         Error *err = NULL;
         if (seed_optarg != NULL) {
@@ -494,7 +490,49 @@  int main(int argc, char **argv)
      * Now that page sizes are configured we can do
      * proper page alignment for guest_base.
      */
-    guest_base = HOST_PAGE_ALIGN(guest_base);
+    if (have_guest_base) {
+        if (guest_base & ~qemu_host_page_mask) {
+            error_report("Selected guest base not host page aligned");
+            exit(1);
+        }
+    }
+
+    /*
+     * If reserving host virtual address space, do so now.
+     * Combined with '-B', ensure that the chosen range is free.
+     */
+    if (reserved_va) {
+        void *p;
+
+        if (have_guest_base) {
+            p = mmap((void *)guest_base, reserved_va + 1, PROT_NONE,
+                     MAP_ANON | MAP_PRIVATE | MAP_FIXED | MAP_EXCL, -1, 0);
+        } else {
+            p = mmap(NULL, reserved_va + 1, PROT_NONE,
+                     MAP_ANON | MAP_PRIVATE, -1, 0);
+        }
+        if (p == MAP_FAILED) {
+            const char *err = strerror(errno);
+            char *sz = size_to_str(reserved_va + 1);
+
+            if (have_guest_base) {
+                error_report("Cannot allocate %s bytes at -B %p for guest "
+                             "address space: %s", sz, (void *)guest_base, err);
+            } else {
+                error_report("Cannot allocate %s bytes for guest "
+                             "address space: %s", sz, err);
+            }
+            exit(1);
+        }
+        guest_base = (uintptr_t)p;
+        have_guest_base = true;
+
+        /* Ensure that mmap_next_start is within range. */
+        if (reserved_va <= mmap_next_start) {
+            mmap_next_start = (reserved_va / 4 * 3)
+                              & TARGET_PAGE_MASK & qemu_host_page_mask;
+        }
+    }
 
     if (loader_exec(filename, argv + optind, target_environ, regs, info,
                     &bprm) != 0) {