From fbe686c008d5c0373188b3738dfe3e75250d3cd7 Mon Sep 17 00:00:00 2001 From: Tu Dinh Date: Tue, 1 Apr 2025 10:36:12 +0000 Subject: Properly limit xenstore write lengths Xenbus's write interface only checks write data sizes using asserts. The size of overly-large writes (e.g. through Xeniface IOCTLs) is not checked in release builds. Verify write lengths using full checks instead of asserts to fix this issue. This is XSA-468 / CVE-2025-27464. Signed-off-by: Tu Dinh Acked-by: Paul Durrant Reviewed-by: Owen Smith --- src/xenbus/store.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/xenbus/store.c b/src/xenbus/store.c index 02d3cc27b5cc..02cdd179ead1 100644 --- a/src/xenbus/store.c +++ b/src/xenbus/store.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -210,6 +211,7 @@ StorePrepareRequest( Segment->Length = sizeof (struct xsd_sockmsg); va_start(Arguments, Type); + status = STATUS_UNSUCCESSFUL; for (;;) { PCHAR Data; ULONG Length; @@ -222,14 +224,19 @@ StorePrepareRequest( break; } + if (Request->Count >= XENBUS_STORE_REQUEST_SEGMENT_COUNT) + goto fail2; Segment = &Request->Segment[Request->Count++]; - ASSERT3U(Request->Count, <, XENBUS_STORE_REQUEST_SEGMENT_COUNT); Segment->Data = Data; Segment->Offset = 0; Segment->Length = Length; - Request->Header.len += Segment->Length; + if (!NT_SUCCESS(RtlULongAdd(Request->Header.len, + Segment->Length, + &Request->Header.len)) || + Request->Header.len > XENSTORE_PAYLOAD_MAX) + goto fail3; } va_end(Arguments); @@ -237,6 +244,10 @@ StorePrepareRequest( return STATUS_SUCCESS; +fail3: +fail2: + RtlZeroMemory(Request, sizeof (XENBUS_STORE_REQUEST)); + fail1: return status; } @@ -1272,10 +1283,12 @@ StoreVPrintf( if (status != STATUS_BUFFER_OVERFLOW) goto fail2; - __StoreFree(Buffer); + status = STATUS_INVALID_BUFFER_SIZE; Length <<= 1; + if (Length > 1024) + goto fail3; - ASSERT3U(Length, <=, 1024); + __StoreFree(Buffer); } status = StoreWrite(Context, @@ -1284,12 +1297,13 @@ StoreVPrintf( Node, Buffer); if (!NT_SUCCESS(status)) - goto fail3; + goto fail4; __StoreFree(Buffer); return STATUS_SUCCESS; +fail4: fail3: fail2: __StoreFree(Buffer); -- 2.47.1