Skip to content

Commit aa612a4

Browse files
r41k0uclaude
andcommitted
Core: Let a packet pointer be narrowed on a store, as C does
convert() refused to narrow a packet pointer below 64 bits, on the premise that the verifier only accepts one at 64 bits. That is true of arithmetic, not of stores: upstream's cgroup_skb_direct_packet_access stores skb->data_end into a __u32 global, and CI's verifier level accepted exactly that on #105. Merging master brought that selftest in and the refusal rejected it. Narrowing now truncates, and the result is an ordinary integer. ctx_data_narrow_store.py moves to the passing tests. Keeping the pointer when a local is declared narrower belongs to allocation (widest type ever stored), noted for later. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent 4cb5f01 commit aa612a4

4 files changed

Lines changed: 14 additions & 15 deletions

File tree

‎pythonbpf/expr/packet_pointer.py‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,14 @@
1717
IntTy tagged with the verifier's kind), and the rules key on that descriptor,
1818
so they follow the pointer through locals (`d = ctx.data`), through
1919
`d + 14`, and into comparisons (`ctx.data + 34 > ctx.data_end` is a 64-bit
20-
unsigned compare). packet-end pointers take no offset at all, and nothing
21-
narrows a packet pointer below 64 bits.
20+
unsigned compare). packet-end pointers take no offset at all.
21+
22+
Storing a packet pointer into a narrower slot truncates it, as C does, and the
23+
result is an ordinary integer: the verifier forbids 32-bit *arithmetic* on a
24+
packet pointer, not a 32-bit store of one (upstream's
25+
cgroup_skb_direct_packet_access stores data_end into a __u32 global). Keeping
26+
the pointer when a local is declared narrower is a job for allocation, which
27+
could give such a slot the widest type ever stored into it.
2228
"""
2329

2430
import ast

‎pythonbpf/expr/type_normalization.py‎

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import logging
22
from llvmlite import ir
33
from .ir_ops import deref_to_depth
4-
from pythonbpf.type_deducer import IntTy, PktPtrTy, signedness
4+
from pythonbpf.type_deducer import IntTy, signedness
55
from .operators import COMPARISON_OPS
66

77
logger = logging.getLogger(__name__)
@@ -52,15 +52,6 @@ def convert(builder, val, from_ty, to_ty):
5252
descriptors (see type_deducer.IntTy); the physical width comes from the
5353
value itself, which may already be wider than its descriptor says.
5454
"""
55-
if (
56-
isinstance(from_ty, PktPtrTy)
57-
and isinstance(to_ty, ir.IntType)
58-
and to_ty.width < 64
59-
):
60-
raise TypeError(
61-
f"a packet pointer ({from_ty.describe()}) cannot be narrowed to "
62-
f"i{to_ty.width}; the verifier only accepts it at 64 bits"
63-
)
6455
if not (isinstance(to_ty, ir.IntType) and isinstance(val.type, ir.IntType)):
6556
# Every caller either checks both sides are integers or sits on a path
6657
# that only carries integers, so reaching here is a type error that

tests/failing_tests/vmlinux/ctx_data_narrow_store.py renamed to tests/passing_tests/vmlinux/ctx_data_narrow_store.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
# A packet pointer stored into a 32-bit slot would lose it; the verifier only
2-
# accepts packet pointers at 64 bits, so the compiler refuses the narrowing.
1+
# A packet pointer stored into a 32-bit local is truncated, as in C
2+
# (`__u32 x = ctx->data`), and is an ordinary integer from then on. The
3+
# verifier forbids 32-bit arithmetic on a packet pointer, not a narrow store
4+
# of one; upstream's cgroup_skb_direct_packet_access does the same with a
5+
# __u32 global.
36
from ctypes import c_int64, c_uint32 # noqa: F401
47
from pythonbpf import bpf, section, bpfglobal, compile
58
from vmlinux import struct_xdp_md

‎tests/test_config.toml‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@
6868
"failing_tests/vmlinux/ctx_data_offset_too_big.py" = {reason = "A constant packet offset outside 0..65535 is a compile error (the verifier tracks packet ranges up to MAX_PACKET_OFF)", level = "ir"}
6969
"failing_tests/vmlinux/ctx_data_end_offset.py" = {reason = "A packet-end pointer can only be compared, not offset (the verifier rejects arithmetic on it)", level = "ir"}
7070

71-
"failing_tests/vmlinux/ctx_data_narrow_store.py" = {reason = "A packet pointer cannot be narrowed below 64 bits", level = "ir"}
7271

7372
"kernel_selftest_equivalent/ringbuf/reserve_submit_discard.py" = {reason = "RingBuffer reserve/typed record/discard workflow is planned but not implemented yet", level = "ir"}
7473

0 commit comments

Comments
 (0)