From: Teddy Astie Subject: Ensure passed ring-page-order is valid The current logic accepts any guest provided ring order, which can cause a stack overflow in tap_ctl_connect_xenblkif() as tapdisk_message_blkif::gref can only store 8 grant references, yet order may be larger than 3. Fix this by checking that ring order values is in [0..3] range. Also clarify the gref array size in tapdisk_message_blkif (fixes TODO). This is XSA-521 / CVE-2026-102701. Signed-off-by: Teddy Astie Reviewed-by: Ross Lagerwall Tested-by: Alex Brett diff --git a/control/tap-ctl-xen.c b/control/tap-ctl-xen.c index f09b76ea8255..37dff06623bf 100644 --- a/control/tap-ctl-xen.c +++ b/control/tap-ctl-xen.c @@ -45,6 +45,8 @@ #include #include +#include "xen_blkif.h" +#include "debug.h" #include "tap-ctl.h" #include "compiler.h" #include "util.h" @@ -58,7 +60,9 @@ tap_ctl_connect_xenblkif(const pid_t pid, const domid_t domid, const int devid, tapdisk_message_t message; int i, err; - memset(&message, 0, sizeof(message)); + ASSERT(order >= 0 && order <= MAX_RING_PAGE_ORDER); + + memset(&message, 0, sizeof(message)); message.type = TAPDISK_MESSAGE_XENBLKIF_CONNECT; message.cookie = minor; diff --git a/include/tapdisk-message.h b/include/tapdisk-message.h index 489017ca6909..7231a14d301c 100644 --- a/include/tapdisk-message.h +++ b/include/tapdisk-message.h @@ -34,6 +34,8 @@ #include #include +#include "xen_blkif.h" + /* * TODO This is quite small since we don't allow path bigger than 256 chars. If * we ever increase this, make sure tapdisk_message_t structures are not @@ -135,9 +137,8 @@ typedef struct tapdisk_message_blkif { /** * Grant references for the shared ring. - * TODO Why 8 specifically? */ - uint32_t gref[8]; + uint32_t gref[MAX_RING_PAGES]; /** * Number of pages in the ring, expressed as a page order. diff --git a/tapback/frontend.c b/tapback/frontend.c index 243f84252dd6..986f45647bf6 100644 --- a/tapback/frontend.c +++ b/tapback/frontend.c @@ -119,6 +119,12 @@ connect_tap(vbd_t * const device) "%d", &order)) order = 0; + if (order < 0 || order > MAX_RING_PAGE_ORDER) { + WARN(device, "front-end asked for an invalid ring order: %d\n", order); + err = EINVAL; + goto out; + } + nr_pages = 1 << order; if (!(gref = calloc(nr_pages, sizeof(grant_ref_t)))) {