Skip to contentSkip to conversation

bpf: allow narrow loads of some sk_reuseport_md fields with offset > 0

PATCH Applied Ilya Leoshkevich 2 participants 2 messages Aug 20, 2019 – Aug 23, 2019

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

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.

Fixes 2dbb9b9e6df6 ("bpf: Introduce BPF_PROG_TYPE_SK_REUSEPORT")
---
 net/core/filter.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
net/core/filter.c +4 -4
index 7878f918b8c0..4c6a252d4212 100644
@@ -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
maintainer Applied
#1 lore raw
Quoted 16 lines · Ilya Leoshkevich

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.

Quoted 5 lines

Ditto for ip_protocol, bind_inany and 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")

Applied, thanks!