]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
bpf: allow narrow loads of some sk_reuseport_md fields with offset > 0
authorIlya Leoshkevich <iii@linux.ibm.com>
Tue, 20 Aug 2019 15:50:25 +0000 (17:50 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 21 Sep 2019 05:18:34 +0000 (07:18 +0200)
[ Upstream commit 2c238177bd7f4b14bdf7447cc1cd9bb791f147e6 ]

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")
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/core/filter.c

index 534c310bb08932a690cbc994d540ca79ed0e3bd2..7aee6f368754ae11950f4deb1845be2fd820795d 100644 (file)
@@ -8553,13 +8553,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);