block: raw_async: reject batch atomically when SQ lacks capacity

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 <dgreid@fb.com>
This commit is contained in:
Dylan Reid
2026-04-24 17:10:44 -07:00
committed by Bo Chen
parent 273e6d53b8
commit 6b44e7b190

View File

@@ -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 => {