]> xenbits.xensource.com Git - people/tklengyel/xen.git/commitdiff
tools/ocaml/xc: Don't reference Abstract_Tag objects with the GC lock released
authorAndrew Cooper <andrew.cooper3@citrix.com>
Tue, 31 Jan 2023 17:19:30 +0000 (17:19 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 9 Feb 2023 15:55:25 +0000 (15:55 +0000)
The intf->{addr,len} references in the xc_map_foreign_range() call are unsafe.
From the manual:

  https://ocaml.org/manual/intfc.html#ss:parallel-execution-long-running-c-code

"After caml_release_runtime_system() was called and until
caml_acquire_runtime_system() is called, the C code must not access any OCaml
data, nor call any function of the run-time system, nor call back into OCaml
code."

More than what the manual says, the intf pointer is (potentially) invalidated
by caml_enter_blocking_section() if another thread happens to perform garbage
collection at just the right (wrong) moment.

Rewrite the logic.  There's no need to stash data in the Ocaml object until
the success path at the very end.

Fixes: 8b7ce06a2d34 ("ocaml: Add XC bindings.")
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Christian Lindig <christian.lindig@citrix.com>
(cherry picked from commit 9e7c74e6f9fd2e44df1212643b80af9032b45b07)

tools/ocaml/libs/xc/xenctrl_stubs.c

index f376d94334b442ae30f76f266a5fe9b9900419cf..facb5615776be5db7a4391fba78238dace983d28 100644 (file)
@@ -953,26 +953,25 @@ CAMLprim value stub_map_foreign_range(value xch, value dom,
        CAMLparam4(xch, dom, size, mfn);
        CAMLlocal1(result);
        struct mmap_interface *intf;
-       uint32_t c_dom;
-       unsigned long c_mfn;
+       unsigned long c_mfn = Nativeint_val(mfn);
+       int len = Int_val(size);
+       void *ptr;
 
        BUILD_BUG_ON((sizeof(struct mmap_interface) % sizeof(value)) != 0);
        result = caml_alloc(Wsize_bsize(sizeof(struct mmap_interface)),
                            Abstract_tag);
 
-       intf = (struct mmap_interface *) result;
-
-       intf->len = Int_val(size);
-
-       c_dom = _D(dom);
-       c_mfn = Nativeint_val(mfn);
        caml_enter_blocking_section();
-       intf->addr = xc_map_foreign_range(_H(xch), c_dom,
-                                         intf->len, PROT_READ|PROT_WRITE,
-                                         c_mfn);
+       ptr = xc_map_foreign_range(_H(xch), _D(dom), len,
+                                  PROT_READ|PROT_WRITE, c_mfn);
        caml_leave_blocking_section();
-       if (!intf->addr)
+
+       if (!ptr)
                caml_failwith("xc_map_foreign_range error");
+
+       intf = Data_abstract_val(result);
+       *intf = (struct mmap_interface){ ptr, len };
+
        CAMLreturn(result);
 }