diff mbox series

[for-4.17,v3,11/15] tools/ocaml/xenstored: do not rebind event channels after live update

Message ID 003537c5db4682b9a5f632d61cb15b332e0778bf.1667920496.git.edvin.torok@citrix.com (mailing list archive)
State New, archived
Headers show
Series OCaml fixes for Xen 4.17 | expand

Commit Message

Edwin Török Nov. 8, 2022, 3:34 p.m. UTC
See explanation in previous commit.
This introduces a new field into the live update stream to retain both
ports, and handles the missing value in a backward compatible way.

Signed-off-by: Edwin Török <edvin.torok@citrix.com>
---
Reason for inclusion 4.17:
- fixes a bug in oxenstored live update, needed to make live updates
  with future 4.17 security fixes possible/more reliable

Changes since v2:
- new in v3
---
 tools/ocaml/libs/eventchn/xeneventchn.ml  |  5 +++++
 tools/ocaml/libs/eventchn/xeneventchn.mli |  5 +++++
 tools/ocaml/xenstored/domain.ml           |  6 +++++-
 tools/ocaml/xenstored/domains.ml          | 13 +++++++++----
 tools/ocaml/xenstored/event.ml            |  1 +
 tools/ocaml/xenstored/xenstored.ml        | 11 +++++++----
 6 files changed, 32 insertions(+), 9 deletions(-)
diff mbox series

Patch

diff --git a/tools/ocaml/libs/eventchn/xeneventchn.ml b/tools/ocaml/libs/eventchn/xeneventchn.ml
index 34f7391f5e..7ccf7a99f0 100644
--- a/tools/ocaml/libs/eventchn/xeneventchn.ml
+++ b/tools/ocaml/libs/eventchn/xeneventchn.ml
@@ -43,6 +43,11 @@  type virq_t =
 
 external notify: handle -> int -> unit = "stub_eventchn_notify"
 external bind_interdomain: handle -> int -> int -> int = "stub_eventchn_bind_interdomain"
+
+let restore_interdomain handle _domid _remote_port local_port =
+  notify handle local_port;
+  local_port
+
 external bind_virq: handle -> virq_t -> int = "stub_eventchn_bind_virq"
 let bind_dom_exc_virq handle = bind_virq handle Dom_exc
 external unbind: handle -> int -> unit = "stub_eventchn_unbind"
diff --git a/tools/ocaml/libs/eventchn/xeneventchn.mli b/tools/ocaml/libs/eventchn/xeneventchn.mli
index 3965b29621..7407031b9e 100644
--- a/tools/ocaml/libs/eventchn/xeneventchn.mli
+++ b/tools/ocaml/libs/eventchn/xeneventchn.mli
@@ -68,6 +68,11 @@  val bind_interdomain : handle -> int -> int -> t
     channel connected to domid:remote_port. On error it will
     throw a Failure exception. *)
 
+val restore_interdomain : handle -> int -> int -> int -> t
+(** [restore_interdomain h domid remote_port local_port] returns a local event
+    channel connected to domid:remote_port. On error it will
+    throw a Failure exception. *)
+
 val bind_dom_exc_virq : handle -> t
 (** Binds a local event channel to the VIRQ_DOM_EXC
     (domain exception VIRQ). On error it will throw a Failure
diff --git a/tools/ocaml/xenstored/domain.ml b/tools/ocaml/xenstored/domain.ml
index 4e62a48e8e..5dad298614 100644
--- a/tools/ocaml/xenstored/domain.ml
+++ b/tools/ocaml/xenstored/domain.ml
@@ -61,7 +61,7 @@  let string_of_port = function
   | Some x -> string_of_int (Xeneventchn.to_int x)
 
 let dump d chan =
-  fprintf chan "dom,%d,%nd,%d\n" d.id d.mfn d.remote_port
+  fprintf chan "dom,%d,%nd,%d,%s\n" d.id d.mfn d.remote_port (string_of_port d.port)
 
 let notify dom = match dom.port with
   | None ->
@@ -77,6 +77,10 @@  let bind_interdomain dom =
   dom.port <- Some (Event.bind_interdomain dom.eventchn dom.id dom.remote_port);
   debug "bound domain %d remote port %d to local port %s" dom.id dom.remote_port (string_of_port dom.port)
 
+let restore_interdomain dom localport =
+  assert (dom.port = None);
+  dom.port <- Some (Event.restore_interdomain dom.eventchn dom.id dom.remote_port localport);
+  debug "restored interdomain %d remote port %d to local port %s" dom.id dom.remote_port (string_of_port dom.port)
 
 let close dom =
   debug "domain %d unbound port %s" dom.id (string_of_port dom.port);
diff --git a/tools/ocaml/xenstored/domains.ml b/tools/ocaml/xenstored/domains.ml
index d5c452d26c..af9fecf2f7 100644
--- a/tools/ocaml/xenstored/domains.ml
+++ b/tools/ocaml/xenstored/domains.ml
@@ -123,17 +123,22 @@  let cleanup doms =
 let resume _doms _domid =
   ()
 
-let create doms domid mfn port =
+let maybe_bind_interdomain restore_localport dom =
+  match restore_localport with
+  | None -> Domain.bind_interdomain dom
+  | Some p -> Domain.restore_interdomain dom p
+
+let create doms domid mfn ?restore_localport port =
   let interface = Xenctrl.map_foreign_range xc domid (Xenmmap.getpagesize()) mfn in
   let dom = Domain.make domid mfn port interface doms.eventchn in
   Hashtbl.add doms.table domid dom;
-  Domain.bind_interdomain dom;
+  maybe_bind_interdomain restore_localport dom;
   dom
 
 let xenstored_kva = ref ""
 let xenstored_port = ref ""
 
-let create0 doms =
+let create0 ?restore_localport doms =
   let port, interface =
     (
       let port = Utils.read_file_single_integer !xenstored_port
@@ -147,7 +152,7 @@  let create0 doms =
   in
   let dom = Domain.make 0 Nativeint.zero port interface doms.eventchn in
   Hashtbl.add doms.table 0 dom;
-  Domain.bind_interdomain dom;
+  maybe_bind_interdomain restore_localport dom;
   Domain.notify dom;
   dom
 
diff --git a/tools/ocaml/xenstored/event.ml b/tools/ocaml/xenstored/event.ml
index 190ca6fcbf..3debe8731d 100644
--- a/tools/ocaml/xenstored/event.ml
+++ b/tools/ocaml/xenstored/event.ml
@@ -29,6 +29,7 @@  let init ?fd () =
 let fd eventchn = Xeneventchn.fd eventchn.handle
 let bind_dom_exc_virq eventchn = eventchn.virq_port <- Some (Xeneventchn.bind_dom_exc_virq eventchn.handle)
 let bind_interdomain eventchn domid port = Xeneventchn.bind_interdomain eventchn.handle domid port
+let restore_interdomain eventchn domid port local_port = Xeneventchn.restore_interdomain eventchn.handle domid port local_port
 let unbind eventchn port = Xeneventchn.unbind eventchn.handle port
 let notify eventchn port = Xeneventchn.notify eventchn.handle port
 let pending eventchn = Xeneventchn.pending eventchn.handle
diff --git a/tools/ocaml/xenstored/xenstored.ml b/tools/ocaml/xenstored/xenstored.ml
index cdd5b5ac67..d4ff24b440 100644
--- a/tools/ocaml/xenstored/xenstored.ml
+++ b/tools/ocaml/xenstored/xenstored.ml
@@ -169,10 +169,13 @@  module DB = struct
             event_f ~eventfd
           | "socket" :: fd :: [] ->
             socket_f ~fd:(int_of_string fd)
-          | "dom" :: domid :: mfn :: port :: []->
+          | "dom" :: domid :: mfn :: port :: rest ->
             domain_f (int_of_string domid)
               (Nativeint.of_string mfn)
               (int_of_string port)
+              (match rest with
+               | [] -> None (* backward compat: old version didn't have it *)
+               | localport :: _ -> Some (int_of_string localport))
           | "watch" :: domid :: path :: token :: [] ->
             watch_f (int_of_string domid)
               (unhexify path) (unhexify token)
@@ -232,13 +235,13 @@  module DB = struct
       else
         warn "Ignoring invalid socket FD %d" fd
     in
-    let domain_f domid mfn port =
+    let domain_f domid mfn port restore_localport =
       let doms = require_doms () in
       let ndom =
         if domid > 0 then
-          Domains.create doms domid mfn port
+          Domains.create doms domid mfn ?restore_localport port
         else
-          Domains.create0 doms
+          Domains.create0 ?restore_localport doms
       in
       Connections.add_domain cons ndom;
     in