Repository navigation
fix(virtio): set WRITE flag on packed used descriptors from len - #539
Merged
Merged
Conversation
Coverage Report for CI Build 42942303169Coverage increased (+0.03%) to 43.663%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats💛 - Coveralls |
Lencerf
force-pushed
the
fix/packed-used-flags
branch
2 times, most recently
from
November 11, 2026 01:47
b53284e to
54c776b
Compare
PackedQueue::set_used() previously loaded the overwritten available descriptor's flags and only toggled AVAIL and USED, preserving stale WRITE, NEXT, and INDIRECT bits in the used descriptor. Per VirtIO 1.4 Sec 2.8.3 and 2.8.4, VIRTQ_DESC_F_WRITE in a used descriptor specifies whether the device wrote any data into any part of the buffer, and Element Length is reserved and ignored by drivers when VIRTQ_DESC_F_WRITE is clear. Consequently, any request starting with a readable header or an indirect descriptor (or completed out of order into a readable slot) produced a used descriptor with WRITE clear even when len > 0, so a driver that ignores Element Length as the spec allows would treat the written length as 0. Conversely, completing a writable slot with len == 0 left WRITE set, and NEXT, which is reserved in used descriptors (Sec 2.8.6), or INDIRECT leaked into used flags. Linux is not affected, since it reads the length of a used descriptor regardless of VIRTQ_DESC_F_WRITE. Construct the used descriptor flags from scratch instead, setting USED | AVAIL from the ring wrap counter and WRITE iff len > 0. Fixes: f97eb72 ("feat(virtio): support packed queue") Signed-off-by: Changyuan Lyu <changyuanl@google.com>
Lencerf
force-pushed
the
fix/packed-used-flags
branch
from
November 11, 2026 01:54
54c776b to
114f808
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PackedQueue::set_used()previously loaded the overwritten available descriptor's flags and only toggledAVAILandUSED, preserving staleWRITE,NEXT, andINDIRECTbits in the used descriptor.Per VirtIO 1.4 Sec 2.8.3 (Write Flag) and Sec 2.8.4 (Element Address and Length),
VIRTQ_DESC_F_WRITEin a used descriptor specifies whether any data was written by the device into any part of the buffer, andElement Lengthis reserved and ignored by drivers whenVIRTQ_DESC_F_WRITEis clear. As a result:virtio-blkIN/GET_ID,virtio-fsFUSE replies,virtio-netcontrolq), an indirect descriptor, or an out-of-order completion overwriting a readable slot produced a used descriptor withWRITE = 0even whenlen > 0, so a driver that ignoresElement Lengthas the spec allows would treat the written length as0.len == 0leftWRITE = 1, andNEXT(reserved in used descriptors, Sec 2.8.6) orINDIRECTleaked into used descriptor flags.Linux guests are not affected:
virtqueue_get_buf_ctx_packed()reads the length withvring_read_packed_desc_len()regardless ofVRING_DESC_F_WRITE, andis_used_desc_packed()only checksAVAILandUSED.Construct the used descriptor flags from scratch instead, setting
USED | AVAILfromindex.wrap_counter()andWRITEifflen > 0.Testing
VirtQueueGuest::get_used()inpacked_test.rsto assert reserved flags (NEXT | INDIRECT) are clear and ignoredesc.lenunlessDescFlag::WRITEis set.enabled_queueand a parameterizedset_used_flagstest, which starts from available descriptors whoseAVAILequals andUSEDdiffers from the wrap counter. Both fail with the previousset_used().cargo +nightly fmt --check,cargo clippy --all-targets -D warningson x86_64-unknown-linux-gnu/musl, aarch64-unknown-linux-gnu and aarch64-apple-darwin, andcargo test --workspacepass locally.