Skip to content

RHEL-183408 viostor: fix overflow in bump allocator bounds checks - #1590

Open
rachael-george wants to merge 1 commit into
virtio-win:masterfrom
rachael-george:VioStorPoolAlloc_overflow
Open

RHEL-183408 viostor: fix overflow in bump allocator bounds checks#1590
rachael-george wants to merge 1 commit into
virtio-win:masterfrom
rachael-george:VioStorPoolAlloc_overflow

Conversation

@rachael-george

Copy link
Copy Markdown

Issue
VioStorPoolAlloc (and the related page bump allocator in virtio_pci.c) checked whether a request fit in the pre-allocated pool using:

(offset + size) <= totalSize

With 32-bit unsigned math, offset + size can wrap around when both values are large. The result can look small, so the check incorrectly passes and the code writes past the end of the buffer via RtlZeroMemory.

The code checked the raw request size but allocated a cache-line- or page-rounded size. A small request near the end of the pool could pass the check yet still overrun when the rounded size was applied.

Fix
Updated both bump allocators to use an overflow-safe bounds check:

  • Round first — compute the actual allocation size (ROUND_TO_CACHE_LINES for the pool, ROUND_TO_PAGES for pages) before checking.

  • Check fit safely — instead of offset + size, use offset > totalSize - alignedSize (with a prior check that alignedSize <= totalSize). This avoids addition wraparound and correctly answers “is there enough space left?”

  • Reject invalid sizes — fail if rounding overflows (alignedSize < size) or the request does not fit.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request improves the safety of memory allocation in mem_alloc_contiguous_pages and VioStorPoolAlloc by introducing robust overflow and bounds checks. Specifically, it ensures that the aligned size does not overflow, does not exceed the total page or pool size, and that the offset calculation remains within bounds. There are no review comments, and we have no additional feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@rachael-george rachael-george changed the title viostor: fix overflow in bump allocator bounds checks [RHEL-183408] viostor: fix overflow in bump allocator bounds checks Jul 7, 2026
@rachael-george rachael-george changed the title [RHEL-183408] viostor: fix overflow in bump allocator bounds checks RHEL-183408 viostor: fix overflow in bump allocator bounds checks Jul 7, 2026

@YanVugenfirer YanVugenfirer left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please squash the commits (with git rebase -i)

@rachael-george
rachael-george force-pushed the VioStorPoolAlloc_overflow branch from 12cc65c to 04d553d Compare July 13, 2026 04:02
@kevmw

kevmw commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Your description of the problem above is good; please add a condensed version of it to the commit message. It would also be good to add a note that the problem is purely theoretical (I assume it is, not the least because the pool sizes are precalculated according to the required memory anyway?) and there is no reproducer.

The fix itself is huge for a rather trivial problem. Not sure why we need all those local variables that are only a copy of struct fields without ever being changed - was this about line lengths with the conditions?

I expected something much more minimal (and obvious) that touches only two lines for each instance, like this:

diff --git a/viostor/virtio_pci.c b/viostor/virtio_pci.c
index 52e52055..50114ab3 100644
--- a/viostor/virtio_pci.c
+++ b/viostor/virtio_pci.c
@@ -124,9 +124,9 @@ static void *mem_alloc_contiguous_pages(void *context, size_t size)
     PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)context;
     PVOID ptr = (PVOID)((ULONG_PTR)adaptExt->pageAllocationVa + adaptExt->pageOffset);
 
-    if ((adaptExt->pageOffset + size) <= adaptExt->pageAllocationSize)
+    size = ROUND_TO_PAGES(size);
+    if (size && size <= adaptExt->pageAllocationSize - adaptExt->pageOffset)
     {
-        size = ROUND_TO_PAGES(size);
         adaptExt->pageOffset += size;
         RtlZeroMemory(ptr, size);
         return ptr;
diff --git a/viostor/virtio_stor.c b/viostor/virtio_stor.c
index f93d0916..7539c5ad 100644
--- a/viostor/virtio_stor.c
+++ b/viostor/virtio_stor.c
@@ -2471,9 +2471,9 @@ VioStorPoolAlloc(IN PVOID DeviceExtension, IN SIZE_T size)
     PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension;
     PVOID ptr = (PVOID)((ULONG_PTR)adaptExt->poolAllocationVa + adaptExt->poolOffset);
 
-    if ((adaptExt->poolOffset + size) <= adaptExt->poolAllocationSize)
+    size = ROUND_TO_CACHE_LINES(size);
+    if (size && size <= adaptExt->poolAllocationSize - adaptExt->poolOffset)
     {
-        size = ROUND_TO_CACHE_LINES(size);
         adaptExt->poolOffset += (ULONG)size;
         RtlZeroMemory(ptr, size);
         return ptr;

Not even sure if the part with checking if size is non-zero is really necessary, but I included it because you have a check if the rounding overflowed, too.

@rachael-george
rachael-george force-pushed the VioStorPoolAlloc_overflow branch from 04d553d to 7b32435 Compare July 17, 2026 07:58
@rachael-george

Copy link
Copy Markdown
Author

Thanks for the review @kevmw . I've reworked it to match your suggestion and updated the commit message.

@kevmw

kevmw commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

The commit message looks good to me now. It would be more conventional to have line breaks after 72 characters or so instead of having really long lines, but that's a minor detail. The important part is that there content is there.

As for the code, I'll have to defer to someone else because it was my own suggestion.

The bump allocators checked bounds using (offset + size) <= totalSize,
which can wrap with unsigned math, and checked the raw size rather
than the rounded allocation size.

Fix: round first, then use subtraction (size <= totalSize - offset)
to avoid wraparound. Purely theoretical — no known reproducer.

Signed-off-by: rachael-george <rgeorge@redhat.com>
@rachael-george
rachael-george force-pushed the VioStorPoolAlloc_overflow branch from 7b32435 to d38ab4a Compare July 24, 2026 06:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants