Route sendmsg/recvmsg via shared host_iov helper#64
Merged
Merged
Conversation
sys_sendmsg and sys_recvmsg resolved each guest iov entry with
guest_ptr_bound() and clamped the entry's length to the contiguous
prefix when the guest VA crossed a host-side discontinuity (primary slab
to guest_mapping / guest_overflow region, or between two distinct
mappings). The loop then continued populating host_iov[i+1..] at full
requested length, so the host sendmsg(2) placed bytes from iov[i+1] on
the wire where the truncated tail of iov[i] belonged, and recvmsg(2)
scattered received bytes into the wrong guest buffer past a truncated
entry. The case only fires when a guest iov entry straddles two distinct
host mappings; the typical single-region iov masked it in tests.
Hoist the already-correct build_host_iov helper from src/syscall/io.c
into src/syscall/internal.h as host_iov_prepare and the wrapper
host_iov_prepare_msg, together with host_iov_buf_t and SYSCALL_IOV_{MAX,
STACK_MAX} constants. host_iov_prepare keeps the strict readv/writev
contract (rejects iovcnt <= 0); host_iov_prepare_msg short-circuits
iovcnt == 0 for ancillary-only sendmsg/recvmsg payloads. Replace the
duplicated inline iov build loops in src/syscall/net-msg.c with the
shared call. Side effects: lifts the per-call iovcnt cap from 64 to
SYSCALL_IOV_MAX (1024) and drops roughly 80 lines of duplicated logic.
The shared helper truncates at the first non-contiguous iov entry and
zeros every subsequent entry, so the host call returns a POSIX-compliant
short I/O instead of mis-aligning the wire data.
Max042004
approved these changes
May 31, 2026
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.
sys_sendmsg and sys_recvmsg resolved each guest iov entry with guest_ptr_bound() and clamped the entry's length to the contiguous prefix when the guest VA crossed a host-side discontinuity (primary slab to guest_mapping / guest_overflow region, or between two distinct mappings). The loop then continued populating host_iov[i+1..] at full requested length, so the host sendmsg(2) placed bytes from iov[i+1] on the wire where the truncated tail of iov[i] belonged, and recvmsg(2) scattered received bytes into the wrong guest buffer past a truncated entry. The case only fires when a guest iov entry straddles two distinct host mappings; the typical single-region iov masked it in tests.
Hoist the already-correct build_host_iov helper from src/syscall/io.c into src/syscall/internal.h as host_iov_prepare and the wrapper host_iov_prepare_msg, together with host_iov_buf_t and the SYSCALL_IOV_MAX / SYSCALL_IOV_STACK_MAX constants. host_iov_prepare keeps the strict readv/writev contract (rejects iovcnt <= 0); host_iov_prepare_msg short-circuits iovcnt == 0 for ancillary-only sendmsg/recvmsg payloads. Replace the duplicated inline iov build loops in src/syscall/net-msg.c with the shared call. Side effects: lifts the per-call iovcnt cap from 64 to SYSCALL_IOV_MAX (1024) and drops roughly 80 lines of duplicated logic.
The shared helper truncates at the first non-contiguous iov entry and zeros every subsequent entry, so the host call returns a POSIX-compliant short I/O instead of mis-aligning the wire data.
Summary by cubic
Fixes misaligned I/O in sendmsg/recvmsg when a guest iovec crosses non‑contiguous host mappings by routing both calls through a shared
host_iovhelper. Lifts the iov cap to 1024 and removes duplicated logic.Bug Fixes
msg_iovlenatSYSCALL_IOV_MAXbefore int narrowing; allowiovcnt == 0for ancillary‑only messages.Refactors
build_host_iovintohost_iov_prepare/host_iov_prepare_msginsrc/syscall/internal.hwithhost_iov_buf_t,host_iov_free, and sharedSYSCALL_IOV_MAX/SYSCALL_IOV_STACK_MAX.src/syscall/net-msg.c; raised per‑call cap from 64 to 1024; removed ~80 lines.readv/writev/pwritev2behavior: zeroiovcntstays-EINVALand does not move the file offset.Written for commit 7a98c58. Summary will update on new commits.