Skip to content

net_packet_capture: fix read_at over-read past segment boundary#3105

Draft
Copilot wants to merge 4 commits intomainfrom
copilot/fix-net-packet-capture-read-at-overread
Draft

net_packet_capture: fix read_at over-read past segment boundary#3105
Copilot wants to merge 4 commits intomainfrom
copilot/fix-net-packet-capture-read-at-overread

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 23, 2026

In both the RX and TX capture paths, copy_length was computed correctly to cap reads at the segment boundary, but the slice passed to read_at was unbounded — reading up to buf.len() - len bytes instead of copy_length. This could pull in bytes from unrelated guest memory, and silently leave stale/zero data in the capture buffer if the over-read crossed into unmapped memory.

Changes

  • rx_poll and tx_avail capture loops: bound the read_at slice to exactly copy_length bytes:
// Before
let copy_length = std::cmp::min(buf.len() - len, segment.len as usize);
let _ = self.mem.read_at(segment.gpa, &mut buf[len..]);

// After
let copy_length = std::cmp::min(buf.len() - len, segment.len as usize);
let _ = self.mem.read_at(segment.gpa, &mut buf[len..len + copy_length]);
  • Add integration tests: 4 tests that drive the actual PacketCaptureQueue through rx_poll and tx_avail using mock inner queues and real GuestMemory. Each test places segments at the end of a 4096-byte guest memory with a large snaplen (65535), so the old unbounded &mut buf[len..] causes read_at to over-read past memory and fail silently — leaving the capture buffer zero-filled. Tests assert the PCAP output contains the expected byte patterns. All 4 tests panic when the fix is reverted.
Original prompt

This section details on the original issue you should resolve

<issue_title>net_packet_capture: read_at over-reads past segment boundary in PCAP capture</issue_title>
<issue_description>In net_packet_capture, both the RX and TX capture paths compute a copy_length to limit how many bytes to capture from each segment, but then pass an unbounded slice to read_at:

let copy_length = std::cmp::min(buf.len() - len, segment.len as usize);
let _ = pool.guest_memory().read_at(segment.gpa, &mut buf[len..]);
//                                                 ^^^^^^^^^ should be &mut buf[len..len + copy_length]

This reads buf.len() - len bytes from guest memory starting at segment.gpa, which can extend past the segment boundary into unrelated guest memory. The PCAP output happens to use the correct length (since len only advances by copy_length), but:

  • Bytes beyond the segment are read into the capture buffer unnecessarily.
  • If the over-read crosses into unmapped guest memory, read_at fails and the let _ = silently swallows the error, leaving stale/zero bytes in the buffer.

Fix: Change both sites to &mut buf[len..len + copy_length].

Affected code: vm/devices/net/net_packet_capture/src/lib.rs — the rx_poll capture loop and the tx_avail capture loop.</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Fix read_at over-reads past segment boundary in net_packet_capture net_packet_capture: fix read_at over-read past segment boundary Mar 23, 2026
Copilot AI requested a review from jstarks March 23, 2026 16:59
@jstarks
Copy link
Copy Markdown
Member

jstarks commented Mar 23, 2026

@copilot, you fixed the bug, but can you add some tests? The tests should be written so that they would have failed (panicked?) before your fix. Temporarily revert your changes locally to validate this.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 23, 2026

@copilot, you fixed the bug, but can you add some tests? The tests should be written so that they would have failed (panicked?) before your fix. Temporarily revert your changes locally...

Added in c81f095. I extracted the duplicated capture loop into a read_segments_to_buf helper (used by both rx_poll and tx_avail) and added 5 unit tests. Two tests specifically target the bug:

  • read_segments_single_segment_at_end_of_memory — segment at GPA 4080 with len=16, snaplen=64. Old code: read_at(4080, &buf[0..64]) → 4144 > 4096 → OutOfRange → buffer stays zeros.
  • read_segments_multiple_segments_at_end_of_memory — two segments near end of page, same failure mode.

I validated by temporarily reverting &mut buf[len..len + copy_length] back to &mut buf[len..] — both tests fail with assertion errors showing [0, 0, ...] vs expected [0xAA, ...].

@jstarks
Copy link
Copy Markdown
Member

jstarks commented Mar 23, 2026

@copilot, this completely misunderstands the purposes of the test. Revert this garbage. The point is to write tests that drive the actual network backend in a way to cause the panic. Not test a tiny bit of isolated code.

… PacketCaptureQueue

Co-authored-by: jstarks <9548354+jstarks@users.noreply.github.com>
Agent-Logs-Url: https://github.com/microsoft/openvmm/sessions/1ce538bd-a302-47a0-b7b0-2e455bf9e1aa
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 23, 2026

@copilot, this completely misunderstands the purposes of the test. Revert this garbage. The point is to write tests that drive the actual network backend in a way to cause the panic. N...

Reverted the read_segments_to_buf extraction and isolated tests in 99da07c. Replaced with 4 integration tests that drive PacketCaptureQueue directly through rx_poll and tx_avail using mock inner queues and real GuestMemory. Each test places segments at the end of a 4096-byte guest memory with a large snaplen (65535), so the old &mut buf[len..] causes read_at to over-read past memory and fail silently — leaving the buffer zero-filled. The tests assert the PCAP output contains the expected byte patterns. All 4 tests panic when the fix is reverted.

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.

net_packet_capture: read_at over-reads past segment boundary in PCAP capture

3 participants