[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH] tools/ocaml/xenctrl: OCaml 5 support, fix use-after-free
The binding for xc_interface_close() free the underlying handle while leaving the Ocaml object still in scope and usable. This would make it easy to suffer a use-after-free, if it weren't for the fact that the typical usage is as a singleton that lives for the lifetime of the program. Ocaml 5 no longer permits storing a naked C pointer in an Ocaml value. Therefore, use a Custom block. This allows us to use the finaliser callback to call xc_interface_close(), if the Ocaml object goes out of scope. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> --- CC: Christian Lindig <christian.lindig@xxxxxxxxxx> CC: David Scott <dave@xxxxxxxxxx> CC: Edwin Torok <edvin.torok@xxxxxxxxxx> CC: Rob Hoes <Rob.Hoes@xxxxxxxxxx> I've confirmed that Xenctrl.close_handle does cause the finaliser to be called, simply by dropping the handle reference. --- tools/ocaml/libs/xc/xenctrl.ml | 3 +-- tools/ocaml/libs/xc/xenctrl.mli | 1 - tools/ocaml/libs/xc/xenctrl_stubs.c | 43 ++++++++++++++++++++++--------------- 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/tools/ocaml/libs/xc/xenctrl.ml b/tools/ocaml/libs/xc/xenctrl.ml index aa650533f718..4b74e31c75cb 100644 --- a/tools/ocaml/libs/xc/xenctrl.ml +++ b/tools/ocaml/libs/xc/xenctrl.ml @@ -175,7 +175,6 @@ exception Error of string type handle external interface_open: unit -> handle = "stub_xc_interface_open" -external interface_close: handle -> unit = "stub_xc_interface_close" let handle = ref None @@ -183,7 +182,7 @@ let get_handle () = !handle let close_handle () = match !handle with - | Some h -> handle := None; interface_close h + | Some h -> handle := None | None -> () let with_intf f = diff --git a/tools/ocaml/libs/xc/xenctrl.mli b/tools/ocaml/libs/xc/xenctrl.mli index 5bf5f5dfea36..ddfe84dc22a9 100644 --- a/tools/ocaml/libs/xc/xenctrl.mli +++ b/tools/ocaml/libs/xc/xenctrl.mli @@ -146,7 +146,6 @@ type shutdown_reason = Poweroff | Reboot | Suspend | Crash | Watchdog | Soft_res exception Error of string type handle external interface_open : unit -> handle = "stub_xc_interface_open" -external interface_close : handle -> unit = "stub_xc_interface_close" (** [with_intf f] runs [f] with a global handle that is opened on demand * and kept open. Conceptually, a client should use either diff --git a/tools/ocaml/libs/xc/xenctrl_stubs.c b/tools/ocaml/libs/xc/xenctrl_stubs.c index f37848ae0bb3..4e1204085422 100644 --- a/tools/ocaml/libs/xc/xenctrl_stubs.c +++ b/tools/ocaml/libs/xc/xenctrl_stubs.c @@ -37,13 +37,28 @@ #include "mmap_stubs.h" -#define _H(__h) ((xc_interface *)(__h)) +#define _H(__h) (*((xc_interface **)Data_custom_val(__h))) #define _D(__d) ((uint32_t)Int_val(__d)) #ifndef Val_none #define Val_none (Val_int(0)) #endif +static void stub_xenctrl_finalize(value v) +{ + xc_interface_close(_H(v)); +} + +static struct custom_operations xenctrl_ops = { + .identifier = "xenctrl", + .finalize = stub_xenctrl_finalize, + .compare = custom_compare_default, /* Can't compare */ + .hash = custom_hash_default, /* Can't hash */ + .serialize = custom_serialize_default, /* Can't serialize */ + .deserialize = custom_deserialize_default, /* Can't deserialize */ + .compare_ext = custom_compare_ext_default, /* Can't compare */ +}; + #define string_of_option_array(array, index) \ ((Field(array, index) == Val_none) ? NULL : String_val(Field(Field(array, index), 0))) @@ -70,26 +85,20 @@ static void Noreturn failwith_xc(xc_interface *xch) CAMLprim value stub_xc_interface_open(void) { CAMLparam0(); - xc_interface *xch; - - /* Don't assert XC_OPENFLAG_NON_REENTRANT because these bindings - * do not prevent re-entrancy to libxc */ - xch = xc_interface_open(NULL, NULL, 0); - if (xch == NULL) - failwith_xc(NULL); - CAMLreturn((value)xch); -} - - -CAMLprim value stub_xc_interface_close(value xch) -{ - CAMLparam1(xch); + CAMLlocal1(result); + xc_interface *xch; caml_enter_blocking_section(); - xc_interface_close(_H(xch)); + xch = xc_interface_open(NULL, NULL, 0); caml_leave_blocking_section(); - CAMLreturn(Val_unit); + if ( !xch ) + failwith_xc(xch); + + result = caml_alloc_custom(&xenctrl_ops, sizeof(xch), 0, 1); + _H(result) = xch; + + CAMLreturn(result); } static void domain_handle_of_uuid_string(xen_domain_handle_t h, -- 2.11.0
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |