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. This is XSA-72 Original ocaml patch by Jerome Maloberti Signed-off-by: Ian Campbell Signed-off-by: Thomas Sanders diff --git a/tools/ocaml/xenstored/connection.ml b/tools/ocaml/xenstored/connection.ml index 273fe4d..47695f8 100644 --- 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)) XSD_ERROR(EROFS), XSD_ERROR(EBUSY), XSD_ERROR(EAGAIN), - XSD_ERROR(EISCONN) + XSD_ERROR(EISCONN), + XSD_ERROR(E2BIG) }; #endif