Skip to content

Add EBPFOpts.PacketStartOffset for non-zero-based PacketStart#45

Open
Dhiver wants to merge 1 commit into
cloudflare:masterfrom
Dhiver:ebpf-packet-start-offset
Open

Add EBPFOpts.PacketStartOffset for non-zero-based PacketStart#45
Dhiver wants to merge 1 commit into
cloudflare:masterfrom
Dhiver:ebpf-packet-start-offset

Conversation

@Dhiver

@Dhiver Dhiver commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

ToEBPF's indirect packet-load guard assumed PacketStart points at offset 0 of the packet. It bounds the data-dependent index against maxStartOffset() = maxPacketOffset - length + 1, relying on the verifier's rule that a packet pointer only gets a range when off + umax_value <= MAX_PACKET_OFF (0xFFFF).

When the caller sets PacketStart to a pointer that already carries a fixed offset (e.g. it points at the L3 header rather than the start of the frame), that fixed offset is added on top of the guarded index. An indirect load with a data-dependent index (such as walking TCP options) can then push off + umax_value past MAX_PACKET_OFF, and the verifier rejects the program with "invalid access to packet" even though the access is safe.

Add EBPFOpts.PacketStartOffset so callers can declare PacketStart's fixed offset. maxStartOffsetWithBase() reserves that many bytes of the packet-offset budget in the indirect guard so the bounded range stays within MAX_PACKET_OFF. It fails closed (returns 0, i.e. noMatch) when no room remains, rather than emitting an unbounded, unverifiable load. maxStartOffsetWithBase also rejects a negative base offset (PacketStart cannot precede the packet) and fails closed, so bogus input never widens the guard's budget.

PacketStartOffset defaults to 0, preserving existing behaviour.

ToEBPF's indirect packet-load guard assumed PacketStart points at
offset 0 of the packet. It bounds the data-dependent index against
maxStartOffset() = maxPacketOffset - length + 1, relying on the
verifier's rule that a packet pointer only gets a range when
off + umax_value <= MAX_PACKET_OFF (0xFFFF).

When the caller sets PacketStart to a pointer that already carries a
fixed offset (e.g. it points at the L3 header rather than the start of
the frame), that fixed offset is added on top of the guarded index. An
indirect load with a data-dependent index (such as walking TCP options)
can then push off + umax_value past MAX_PACKET_OFF, and the verifier
rejects the program with "invalid access to packet" even though the
access is safe.

Add EBPFOpts.PacketStartOffset so callers can declare PacketStart's
fixed offset. maxStartOffsetWithBase() reserves that many bytes of the
packet-offset budget in the indirect guard so the bounded range stays
within MAX_PACKET_OFF. It fails closed (returns 0, i.e. noMatch) when no
room remains, rather than emitting an unbounded, unverifiable load.
maxStartOffsetWithBase also rejects a negative base offset (PacketStart
cannot precede the packet) and fails closed, so bogus input never widens
the guard's budget.

PacketStartOffset defaults to 0, preserving existing behaviour.
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.

1 participant