From 6b44e7b190f26bb8933fc357ff5b4a4e37b31e78 Mon Sep 17 00:00:00 2001 From: Dylan Reid Date: Fri, 24 Apr 2026 17:10:44 -0700 Subject: [PATCH] block: raw_async: reject batch atomically when SQ lacks capacity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit submit_batch_requests pushed each BatchRequest into the io_uring SQ in turn and used `?` to bail on the first push failure. Leaving the initial SQEs visible to the kernel — but submitter.submit() was never called, and every other call site in this file gates submit() behind a preceding sq.push() that now also fails on the full ring. This could allow a guest to DoS it's own queue or worse if the buffer is freed early. Signed-off-by: Dylan Reid --- block/src/raw_async.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/block/src/raw_async.rs b/block/src/raw_async.rs index c0432e35b..79c84c05a 100644 --- a/block/src/raw_async.rs +++ b/block/src/raw_async.rs @@ -161,6 +161,14 @@ impl AsyncIo for RawFileAsync { let (submitter, mut sq, _) = self.io_uring.split(); let mut submitted = false; + // Refuse the whole batch if it can't fit in the SQ to avoid having to unroll a partially + // successful push. + if batch_request.len() > sq.capacity() - sq.len() { + return Err(AsyncIoError::SubmitBatchRequests(Error::other( + "io_uring submission queue is full", + ))); + } + for req in batch_request { match req.request_type { RequestType::In => {