Project

General

Profile

Actions

Security #8777

open
PA

netmap:Multi-Slot Packet Over-read

Security #8777: netmap:Multi-Slot Packet Over-read

Added by Philippe Antoine 1 day ago. Updated 1 day ago.

Status:
Feedback
Priority:
Normal
Assignee:
-
Target version:
Affected Versions:
Label:
CVE:
Git IDs:
Severity:
Disclosure Date:
GHSA:

Description

Original report

# Netmap Multi-Slot Packets Read and Forward Unrelated Buffer Bytes

## Summary

Suricata's netmap reader correctly notices when a packet's slots are not
contiguous, but it still passes the total multi-slot packet length with a
pointer to only the first slot. BPF filtering, zero-copy packet setup, and the
copy path all use the total length rather than the computed contiguous capture
length. A remotely supplied packet split across non-adjacent netmap buffers can
therefore cause an out-of-bounds read from the first buffer.

The invalid pointer/length pair persists in the `Packet`. In netmap tap or IPS
copy mode, the release callback passes it to `nmport_inject`, which transmits
the requested length to the destination interface. PCAP logging likewise dumps
the claimed packet length. The bytes after the first logical buffer can
therefore be disclosed on another network segment or persisted in a capture,
in addition to the existing crash risk.

## Affected Assets & Attack Surface

- `suricata/src/source-netmap.c:666-705`
  - `NetmapProcessPacket`
- `suricata/src/source-netmap.c:714-780`
  - `NetmapReadPackets`
- `suricata/src/source-netmap.c:603-663`
  - `NetmapWritePacket` and `NetmapReleasePacket` forward the invalid
    pointer/length pair
- `suricata/src/log-pcap.c:608-719`
  - PCAP headers and `pcap_dump` use `GET_PKT_LEN` with the same packet pointer
- `suricata/src/decode.c:868-877`
  - `PacketSetData`

The attacker-controlled input is a link-layer frame large enough to occupy
multiple netmap slots. The relevant backend and interface must permit
multi-slot reception; jumbo frames are a common trigger.

The crossed trust boundary is:

```text
wire frame -> kernel/netmap slot array -> user-space pointer/length pair
 -> BPF or packet copy/decoder -> release/log callback
 -> destination netmap interface or PCAP file
```

## Technical Root Cause Analysis

At the first slot, `hdr.buf` points to that slot and both `hdr.len` and
`hdr.caplen` equal its length. For every `NS_MOREFRAG` slot,
`NetmapReadPackets` always adds the slot length to `hdr.len`. It extends
`hdr.caplen` only when:

- the next netmap buffer is exactly one netmap buffer after the previous one;
  and
- the previous slot occupied the entire buffer.

If either condition fails, `oldbuf` is set to null and `caplen` stops growing.
That is an explicit recognition that the remainder is not safely addressable
from `hdr.buf`.

`NetmapProcessPacket` never uses `ph->caplen`. It constructs the BPF header with
`ph->len`, calls `pcap_offline_filter` on `ph->buf`, and passes `ph->len` to
both `PacketSetData` and `PacketCopyData`. `PacketSetData` records that length
without checking the backing extent. The copy path immediately reads the same
out-of-range extent.

No downstream step restores the slot vector. `NetmapReleasePacket` calls
`NetmapWritePacket` for every non-pseudo packet when copy mode is `tap` or
`ips`; `NetmapWritePacket` calls:

```text
nmport_inject(ifdst, GET_PKT_DATA(p), GET_PKT_LEN(p))
```

The injected range begins at the first slot but includes bytes from physically
following netmap buffers, not the packet's non-adjacent continuation slots.
Those buffers can contain another packet or stale ring data. `PcapLog` follows
the same logical error by setting `caplen` to `GET_PKT_LEN` and passing the
packet pointer to `pcap_dump`.

## Proof of Concept & Evidence

Source-proven condition:

```text
first slot buffer = B0, length = L0
second slot buffer = Bn, where Bn is not adjacent to B0
hdr.buf = B0
hdr.caplen = L0
hdr.len = L0 + Ln
NetmapProcessPacket(..., hdr.buf, hdr.len)
```

A non-weaponized validation can configure a netmap test ring with a multi-slot
packet whose second `buf_idx` is non-adjacent. Run once with a BPF program and
once in copy mode under AddressSanitizer. Confirm that the requested read
extends past the first buffer. A control case with physically adjacent,
full-size buffers should not trigger.

For the disclosure path, place a harmless marker in the physically adjacent
buffer and different continuation data in the actual second slot. Use tap or
IPS copy mode and capture the destination interface. Confirm that the forwarded
frame contains the adjacent-buffer marker instead of the second-slot bytes.
Repeat with PCAP logging and confirm that the marker is persisted. A lab IPv4
UDP frame with a zero UDP checksum can keep the corrupted payload acceptable
to a controlled receiver without relying on checksum repair.

The slot loop contains no later coalescing operation. Packet-length checks in
protocol decoders cannot prevent the acquisition-layer read because the invalid
pointer/length pair is created before decoding.

## Impact Assessment

The verified impacts are:

- remote process termination when the over-read reaches inaccessible memory;
- disclosure of unrelated or stale netmap-buffer bytes to the configured
  copy interface in tap/IPS mode;
- persistence of those bytes in enabled PCAP output; and
- injection of a frame whose payload differs from the packet received in the
  actual continuation slots.

The disclosure is bounded by the attacker-selected frame length and the
layout/content of adjacent netmap buffers; it is not an arbitrary-address read.
No out-of-bounds write or code execution is claimed.

## Remediation Guidance

### Code Fix

- Coalesce every multi-slot packet into a packet-owned contiguous buffer before
  BPF evaluation or decoder dispatch.
- Use checked arithmetic when summing slot lengths and reject totals exceeding
  Suricata's maximum packet allocation.
- Validate ring termination so malformed or changing slot flags cannot walk
  indefinitely or wrap into unrelated packet slots.
- If zero-copy must be retained, restrict it to a single slot or to a
  positively verified contiguous run; otherwise fall back to coalescing.
- Never substitute `caplen` as a silent truncation fix for IPS processing,
  because that would convert memory unsafety into a visibility differential.
- Add non-adjacent, adjacent, ring-wrap, zero-length, and maximum-length
  multi-slot regression tests under ASan.

## Risk Classification

- Severity: High
- Estimated CVSS v3.1: 8.6
- CVSS vector: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:H`
- CWE: CWE-125 (Out-of-bounds Read), CWE-126 (Buffer Over-read), CWE-200
  (Exposure of Sensitive Information)
- Affected source baseline: `suricata` `9.0.0-dev` at commit
  `8455efd9ac9be052f5f5424805559611e8531b16`
- Affected modes: netmap live capture in IDS or IPS configurations
- Confirmed impact: remotely triggered denial of service; cross-buffer
  disclosure/injection in netmap copy modes; disclosure to enabled PCAP output


Files

Suricata_PoC.7z (12.8 KB) Suricata_PoC.7z Philippe Antoine, 07/31/2026 09:54 AM
Actions

Also available in: PDF Atom