summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '0083-tools-ocaml-Ensure-packet-size-is-never-negative.patch')
-rw-r--r--0083-tools-ocaml-Ensure-packet-size-is-never-negative.patch75
1 files changed, 75 insertions, 0 deletions
diff --git a/0083-tools-ocaml-Ensure-packet-size-is-never-negative.patch b/0083-tools-ocaml-Ensure-packet-size-is-never-negative.patch
new file mode 100644
index 0000000..5fc3c77
--- /dev/null
+++ b/0083-tools-ocaml-Ensure-packet-size-is-never-negative.patch
@@ -0,0 +1,75 @@
+From 635390415f4a9c0621330f0b40f8c7e914c4523f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Edwin=20T=C3=B6r=C3=B6k?= <edvin.torok@citrix.com>
+Date: Wed, 12 Oct 2022 19:13:05 +0100
+Subject: [PATCH 83/87] tools/ocaml: Ensure packet size is never negative
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Integers in Ocaml have 63 or 31 bits of signed precision.
+
+On 64-bit builds of Ocaml, this is fine because a C uint32_t always fits
+within a 63-bit signed integer.
+
+In 32-bit builds of Ocaml, this goes wrong. The C uint32_t is truncated
+first (loses the top bit), then has a unsigned/signed mismatch.
+
+A "negative" value (i.e. a packet on the ring of between 1G and 2G in size)
+will trigger an exception later in Bytes.make in xb.ml, and because the packet
+is not removed from the ring, the exception re-triggers on every subsequent
+query, creating a livelock.
+
+Fix both the source of the exception in Xb, and as defence in depth, mark the
+domain as bad for any Invalid_argument exceptions to avoid the risk of
+livelock.
+
+This is XSA-420 / CVE-2022-42324.
+
+Signed-off-by: Edwin Török <edvin.torok@citrix.com>
+Acked-by: Christian Lindig <christian.lindig@citrix.com>
+(cherry picked from commit ae34df4d82636f4c82700b447ea2c93b9f82b3f3)
+---
+ tools/ocaml/libs/xb/partial.ml | 6 +++---
+ tools/ocaml/xenstored/process.ml | 2 +-
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/tools/ocaml/libs/xb/partial.ml b/tools/ocaml/libs/xb/partial.ml
+index b6e2a716e263..3aa8927eb7f0 100644
+--- a/tools/ocaml/libs/xb/partial.ml
++++ b/tools/ocaml/libs/xb/partial.ml
+@@ -36,7 +36,7 @@ let of_string s =
+ This will leave the guest connection is a bad state and will
+ be hard to recover from without restarting the connection
+ (ie rebooting the guest) *)
+- let dlen = min xenstore_payload_max dlen in
++ let dlen = max 0 (min xenstore_payload_max dlen) in
+ {
+ tid = tid;
+ rid = rid;
+@@ -46,8 +46,8 @@ let of_string s =
+ }
+
+ let append pkt s sz =
+- if pkt.len > 4096 then failwith "Buffer.add: cannot grow buffer";
+- Buffer.add_string pkt.buf (String.sub s 0 sz)
++ if Buffer.length pkt.buf + sz > xenstore_payload_max then failwith "Buffer.add: cannot grow buffer";
++ Buffer.add_substring pkt.buf s 0 sz
+
+ let to_complete pkt =
+ pkt.len - (Buffer.length pkt.buf)
+diff --git a/tools/ocaml/xenstored/process.ml b/tools/ocaml/xenstored/process.ml
+index ce39ce28b5f3..6cb990ee7fb2 100644
+--- a/tools/ocaml/xenstored/process.ml
++++ b/tools/ocaml/xenstored/process.ml
+@@ -722,7 +722,7 @@ let do_input store cons doms con =
+ History.reconnect con;
+ info "%s reconnection complete" (Connection.get_domstr con);
+ None
+- | Failure exp ->
++ | Invalid_argument exp | Failure exp ->
+ error "caught exception %s" exp;
+ error "got a bad client %s" (sprintf "%-8s" (Connection.get_domstr con));
+ Connection.mark_as_bad con;
+--
+2.37.4
+