bpf: allow narrow loads of some sk_reuseport_md fields with offset > 0
Subsystems (3)
PATCH 1/1 bpf: allow narrow loads of some sk_reuseport_md fields with offset > 0
test_select_reuseport fails on s390 due to verifier rejecting test_select_reuseport_kern.o with the following message:
; data_check.eth_protocol = reuse_md->eth_protocol; 18: (69) r1 = *(u16 *)(r6 +22) invalid bpf_context access off=22 size=2
This is because on big-endian machines casts from __u32 to __u16 are generated by referencing the respective variable as __u16 with an offset of 2 (as opposed to 0 on little-endian machines).
The verifier already has all the infrastructure in place to allow such accesses, it's just that they are not explicitly enabled for eth_protocol field. Enable them for eth_protocol field by using bpf_ctx_range instead of offsetof.
Ditto for ip_protocol, bind_inany and len, since they already allow narrowing, and the same problem can arise when working with them.
--- net/core/filter.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
net/core/filter.c +4 -4
@@ -8757,13 +8757,13 @@ sk_reuseport_is_valid_access(int off, int size,return size == size_default;/* Fields that allow narrowing */ -case offsetof(struct sk_reuseport_md , eth_protocol): + case bpf_ctx_range(struct sk_reuseport_md, eth_protocol): if (size < FIELD_SIZEOF(struct sk_buff, protocol))return false;/* fall through */ -case offsetof(struct sk_reuseport_md , ip_protocol): -case offsetof(struct sk_reuseport_md , bind_inany): -case offsetof(struct sk_reuseport_md , len): + case bpf_ctx_range(struct sk_reuseport_md, ip_protocol): + case bpf_ctx_range(struct sk_reuseport_md, bind_inany): + case bpf_ctx_range(struct sk_reuseport_md, len):bpf_ctx_record_field_size (info, size_default);return bpf_ctx_narrow_access_ok (off, size, size_default);
Signature · 1 line
2.21.0
Quoted 16 lines · Ilya Leoshkevich
test_select_reuseportfails on s390 due to verifier rejecting test_select_reuseport_kern.o with the following message:; data_check.eth_protocol = reuse_md->eth_protocol; 18: (69) r1 = *(u16 *)(r6 +22) invalid bpf_context access off=22 size=2This is because on big-endian machines casts from
__u32to__u16are generated by referencing the respective variable as__u16with an offset of 2 (as opposed to 0 on little-endian machines).The verifier already has all the infrastructure in place to allow such accesses, it's just that they are not explicitly enabled for
eth_protocolfield. Enable them foreth_protocolfield by usingbpf_ctx_rangeinstead of offsetof.
Quoted 5 lines
Ditto for
ip_protocol,bind_inanyand len, since they already allow narrowing, and the same problem can arise when working with them.Fixes 2dbb9b9e6df6 ("bpf: Introduce BPF_PROG_TYPE_SK_REUSEPORT")Signed-off-by Ilya Leoshkevich <[email protected]>
Applied, thanks!