ocaml xenstored mishandles oversized message replies

The Ocaml xenstored implementation (oxenstored) cannot correctly handle a message reply larger than XENSTORE_PAYLOAD_SIZE when communicating with a client domain via the shared ring mechanism.

When this situation occurs the connection to the client domain will be shutdown and cannot be restarted leading to a denial of service to that domain.

improper error handling (unecessary crash)



tools: xenstored: if the reply is too big then send E2BIG error

This fixes the issue for both C and ocaml xenstored, however only the ocaml xenstored is vulnerable in its default configuration.

Adding a new error appears to be safe, since bit libxenstore and the Linux driver at least treat an unknown error code as EINVAL.

--- a/tools/ocaml/xenstored/connection.ml
+++ b/tools/ocaml/xenstored/connection.ml
@@ -18,6 +18,8 @@ exception End_of_file
 open Stdext
+let xenstore_payload_max = 4096 (* xen/include/public/io/xs_wire.h *)
 type watch = {
    con: t;
    token: string;
@@ -112,8 +114,15 @@ let restrict con domid =
 let set_target con target_domid =
    con.perm <- Perms.Connection.set_target (get_perm con) ~perms:[Perms.READ; Perms.WRITE] target_domid
+let is_backend_mmap con = match con.xb.Xenbus.Xb.backend with
+   | Xenbus.Xb.Xenmmap _ -> true
+   | _ -> false
 let send_reply con tid rid ty data =
-   Xenbus.Xb.queue con.xb (Xenbus.Xb.Packet.create tid rid ty data)
+   if (String.length data) > xenstore_payload_max && (is_backend_mmap con) then
+       Xenbus.Xb.queue con.xb (Xenbus.Xb.Packet.create tid rid Xenbus.Xb.Op.Error "E2BIG\000")
+   else
+       Xenbus.Xb.queue con.xb (Xenbus.Xb.Packet.create tid rid ty data)
 let send_error con tid rid err = send_reply con tid rid Xenbus.Xb.Op.Error (err ^ "\000")
 let send_ack con tid rid ty = send_reply con tid rid ty "OK\000"
diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
index 0f8ba64..ccfdaa3 100644
--- a/tools/xenstore/xenstored_core.c
+++ b/tools/xenstore/xenstored_core.c
@@ -629,6 +629,11 @@ void send_reply(struct connection *conn, enum xsd_sockmsg_type type,
    struct buffered_data *bdata;
+   if ( len > XENSTORE_PAYLOAD_MAX ) {
+       send_error(conn, E2BIG);
+       return;
+   }
    /* Message is a child of the connection context for auto-cleanup. */
    bdata = new_buffer(conn);
    bdata->buffer = talloc_array(bdata, char, len);
diff --git a/xen/include/public/io/xs_wire.h b/xen/include/public/io/xs_wire.h
index 99d24e3..585f0c8 100644
--- a/xen/include/public/io/xs_wire.h
+++ b/xen/include/public/io/xs_wire.h
@@ -83,7 +83,8 @@ __attribute__((unused))


A malicious domain can create a directory containing a large number of entries in the hopes that a victim domain will attempt to list the contents of that directory. If this happens then the victim domain’s xenstore connection will be shutdown leading to a denial of service against that domain.

If the victim domain is a toolstack or control domain then this can lead to a denial of service against the whole system.