Skip to content

Fix sendmsg/recvmsg data corruption in bsdsocket emulation#1790

Merged
midwan merged 1 commit intoBlitterStudio:masterfrom
tbdye:fix/sendmsg-recvmsg
Feb 16, 2026
Merged

Fix sendmsg/recvmsg data corruption in bsdsocket emulation#1790
midwan merged 1 commit intoBlitterStudio:masterfrom
tbdye:fix/sendmsg-recvmsg

Conversation

@tbdye
Copy link
Contributor

@tbdye tbdye commented Feb 16, 2026

Problem

sendmsg() in the bsdsocket emulation silently sent data from the wrong memory location. The host_sendto() function (POSIX path) always assigned sb->buf = get_real_address(msg) regardless of whether a host-side buffer was provided via hmsg. When called from bsdsocklib_sendmsg(), msg is 0 and hmsg points to the coalesced iovec data — so get_real_address(0) resolved to natmem_offset (Amiga address 0) instead of the actual data buffer. The worker thread then sent whatever was at the start of Amiga chip RAM.

Two additional bugs existed in the sendmsg/recvmsg trap handlers:

  • bsdsocklib_sendmsg() passed the Amiga address of the msg_namelen field as tolen to host_sendto(), but the worker thread uses tolen as a length value. This broke UDP sendmsg() with a destination address, since copysockaddr_a2n() received a multi-million-byte "length" and rejected it.

  • bsdsocklib_recvmsg() used ftable[sd - 1] with a 0-based socket descriptor, causing an off-by-one in MSG_TRUNC detection. For socket 0 this was an out-of-bounds read (ftable[-1]); for all others it checked the wrong socket's flags.

Fix

Three targeted changes:

  1. host_sendto(): Use realpt (which already handles both the normal send/sendto path and the sendmsg path) instead of unconditionally calling get_real_address(msg). This matches how host_recvfrom() already works.

  2. bsdsocklib_sendmsg(): Read the msg_namelen value with trap_get_long() before passing to host_sendto(), consistent with how normal sendto() passes tolen from the D3 register.

  3. bsdsocklib_recvmsg(): Use ftable[sd] instead of ftable[sd - 1] for correct 0-based indexing.

Validation

Tested with bsdsocktest 0.2.2 (142 tests):

Run Passed Failed Known Skipped
Before (loopback) 116 0 11 15
After (loopback) 118 0 9 15
After (with host helper) 130 0 9 3

Tests fixed: 31 (sendmsg/recvmsg single iovec), 32 (sendmsg/recvmsg scatter-gather). No regressions across all 142 tests.

🤖 Generated with Claude Code

sendmsg() sent data from the wrong buffer because host_sendto() always
used get_real_address(msg) for sb->buf, ignoring the pre-computed realpt
variable. When called from bsdsocklib_sendmsg(), msg is 0 (not an Amiga
buffer address) and hmsg points to the coalesced iovec data. The worker
thread received natmem_offset+0 (start of Amiga RAM) instead of the
actual data buffer, silently corrupting all sendmsg transfers.

Also fixes two secondary bugs in the sendmsg/recvmsg trap handlers:
- sendmsg passed the Amiga address of msg_namelen as tolen instead of
  reading its value, breaking UDP sendmsg with a destination address
- recvmsg used ftable[sd-1] with 0-based sd, causing an off-by-one
  in MSG_TRUNC detection (out-of-bounds for socket 0)

Validated with bsdsocktest 0.2.2 (142 tests):
- Before: 116 passed, 11 known failures
- After:  130 passed, 9 known failures (with host helper)
- Tests fixed: 31 (sendmsg single iovec), 32 (sendmsg scatter-gather)
- No regressions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@tbdye tbdye requested a review from midwan as a code owner February 16, 2026 19:49
@midwan midwan merged commit 0c8da98 into BlitterStudio:master Feb 16, 2026
15 of 16 checks passed
@tbdye tbdye deleted the fix/sendmsg-recvmsg branch February 16, 2026 20:43
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.

2 participants