On Wed, Sep 9, 2020 at 6:59 PM Ilya Leoshkevich <iii@xxxxxxxxxxxxx> wrote: > > This test makes a lot of narrow load checks while assuming little > endian architecture, and therefore fails on s390. > > Fix by introducing LSB and LSW macros and using them to perform narrow > loads. > > Fixes: 0ab5539f8584 ("selftests/bpf: Tests for BPF_SK_LOOKUP attach point") > Signed-off-by: Ilya Leoshkevich <iii@xxxxxxxxxxxxx> > --- Jakub, Can you please help review this to make sure no error accidentally slipped in? > .../selftests/bpf/progs/test_sk_lookup.c | 264 ++++++++++-------- > 1 file changed, 149 insertions(+), 115 deletions(-) > > diff --git a/tools/testing/selftests/bpf/progs/test_sk_lookup.c b/tools/testing/selftests/bpf/progs/test_sk_lookup.c > index bbf8296f4d66..94e6d370967b 100644 > --- a/tools/testing/selftests/bpf/progs/test_sk_lookup.c > +++ b/tools/testing/selftests/bpf/progs/test_sk_lookup.c > @@ -19,6 +19,17 @@ > #define IP6(aaaa, bbbb, cccc, dddd) \ > { bpf_htonl(aaaa), bpf_htonl(bbbb), bpf_htonl(cccc), bpf_htonl(dddd) } > > +/* Macros for least-significant byte and word accesses. */ > +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ > +#define LSE_INDEX(index, size) (index) > +#else > +#define LSE_INDEX(index, size) ((size) - (index) - 1) > +#endif > +#define LSB(value, index) \ > + (((__u8 *)&(value))[LSE_INDEX((index), sizeof(value))]) > +#define LSW(value, index) \ > + (((__u16 *)&(value))[LSE_INDEX((index), sizeof(value) / 2)]) > + > #define MAX_SOCKS 32 > > struct { > @@ -369,171 +380,194 @@ int ctx_narrow_access(struct bpf_sk_lookup *ctx) > { > struct bpf_sock *sk; > int err, family; > - __u16 *half; > - __u8 *byte; > bool v4; > > v4 = (ctx->family == AF_INET); > > /* Narrow loads from family field */ > - byte = (__u8 *)&ctx->family; > - half = (__u16 *)&ctx->family; > - if (byte[0] != (v4 ? AF_INET : AF_INET6) || > - byte[1] != 0 || byte[2] != 0 || byte[3] != 0) > + if (LSB(ctx->family, 0) != (v4 ? AF_INET : AF_INET6) || > + LSB(ctx->family, 1) != 0 || LSB(ctx->family, 2) != 0 || > + LSB(ctx->family, 3) != 0) > return SK_DROP; > - if (half[0] != (v4 ? AF_INET : AF_INET6)) > + if (LSW(ctx->family, 0) != (v4 ? AF_INET : AF_INET6)) > return SK_DROP; > > - byte = (__u8 *)&ctx->protocol; > - if (byte[0] != IPPROTO_TCP || > - byte[1] != 0 || byte[2] != 0 || byte[3] != 0) > + /* Narrow loads from protocol field */ > + if (LSB(ctx->protocol, 0) != IPPROTO_TCP || > + LSB(ctx->protocol, 1) != 0 || LSB(ctx->protocol, 2) != 0 || > + LSB(ctx->protocol, 3) != 0) > return SK_DROP; > - half = (__u16 *)&ctx->protocol; > - if (half[0] != IPPROTO_TCP) > + if (LSW(ctx->protocol, 0) != IPPROTO_TCP) > return SK_DROP; > > /* Narrow loads from remote_port field. Expect non-0 value. */ > - byte = (__u8 *)&ctx->remote_port; > - if (byte[0] == 0 && byte[1] == 0 && byte[2] == 0 && byte[3] == 0) > + if (LSB(ctx->remote_port, 0) == 0 && LSB(ctx->remote_port, 1) == 0 && > + LSB(ctx->remote_port, 2) == 0 && LSB(ctx->remote_port, 3) == 0) > return SK_DROP; > - half = (__u16 *)&ctx->remote_port; > - if (half[0] == 0) > + if (LSW(ctx->remote_port, 0) == 0) > return SK_DROP; > > /* Narrow loads from local_port field. Expect DST_PORT. */ > - byte = (__u8 *)&ctx->local_port; > - if (byte[0] != ((DST_PORT >> 0) & 0xff) || > - byte[1] != ((DST_PORT >> 8) & 0xff) || > - byte[2] != 0 || byte[3] != 0) > + if (LSB(ctx->local_port, 0) != ((DST_PORT >> 0) & 0xff) || > + LSB(ctx->local_port, 1) != ((DST_PORT >> 8) & 0xff) || > + LSB(ctx->local_port, 2) != 0 || LSB(ctx->local_port, 3) != 0) > return SK_DROP; > - half = (__u16 *)&ctx->local_port; > - if (half[0] != DST_PORT) > + if (LSW(ctx->local_port, 0) != DST_PORT) > return SK_DROP; > > /* Narrow loads from IPv4 fields */ > if (v4) { > /* Expect non-0.0.0.0 in remote_ip4 */ > - byte = (__u8 *)&ctx->remote_ip4; > - if (byte[0] == 0 && byte[1] == 0 && > - byte[2] == 0 && byte[3] == 0) > + if (LSB(ctx->remote_ip4, 0) == 0 && > + LSB(ctx->remote_ip4, 1) == 0 && > + LSB(ctx->remote_ip4, 2) == 0 && > + LSB(ctx->remote_ip4, 3) == 0) > return SK_DROP; > - half = (__u16 *)&ctx->remote_ip4; > - if (half[0] == 0 && half[1] == 0) > + if (LSW(ctx->remote_ip4, 0) == 0 && > + LSW(ctx->remote_ip4, 1) == 0) > return SK_DROP; > > /* Expect DST_IP4 in local_ip4 */ > - byte = (__u8 *)&ctx->local_ip4; > - if (byte[0] != ((DST_IP4 >> 0) & 0xff) || > - byte[1] != ((DST_IP4 >> 8) & 0xff) || > - byte[2] != ((DST_IP4 >> 16) & 0xff) || > - byte[3] != ((DST_IP4 >> 24) & 0xff)) > + if (LSB(ctx->local_ip4, 0) != ((DST_IP4 >> 0) & 0xff) || > + LSB(ctx->local_ip4, 1) != ((DST_IP4 >> 8) & 0xff) || > + LSB(ctx->local_ip4, 2) != ((DST_IP4 >> 16) & 0xff) || > + LSB(ctx->local_ip4, 3) != ((DST_IP4 >> 24) & 0xff)) > return SK_DROP; > - half = (__u16 *)&ctx->local_ip4; > - if (half[0] != ((DST_IP4 >> 0) & 0xffff) || > - half[1] != ((DST_IP4 >> 16) & 0xffff)) > + if (LSW(ctx->local_ip4, 0) != ((DST_IP4 >> 0) & 0xffff) || > + LSW(ctx->local_ip4, 1) != ((DST_IP4 >> 16) & 0xffff)) > return SK_DROP; > } else { > /* Expect 0.0.0.0 IPs when family != AF_INET */ > - byte = (__u8 *)&ctx->remote_ip4; > - if (byte[0] != 0 || byte[1] != 0 && > - byte[2] != 0 || byte[3] != 0) > + if (LSB(ctx->remote_ip4, 0) != 0 || > + LSB(ctx->remote_ip4, 1) != 0 || > + LSB(ctx->remote_ip4, 2) != 0 || > + LSB(ctx->remote_ip4, 3) != 0) > return SK_DROP; > - half = (__u16 *)&ctx->remote_ip4; > - if (half[0] != 0 || half[1] != 0) > + if (LSW(ctx->remote_ip4, 0) != 0 || > + LSW(ctx->remote_ip4, 1) != 0) > return SK_DROP; > > - byte = (__u8 *)&ctx->local_ip4; > - if (byte[0] != 0 || byte[1] != 0 && > - byte[2] != 0 || byte[3] != 0) > + if (LSB(ctx->local_ip4, 0) != 0 || > + LSB(ctx->local_ip4, 1) != 0 || > + LSB(ctx->local_ip4, 2) != 0 || LSB(ctx->local_ip4, 3) != 0) > return SK_DROP; > - half = (__u16 *)&ctx->local_ip4; > - if (half[0] != 0 || half[1] != 0) > + if (LSW(ctx->local_ip4, 0) != 0 || LSW(ctx->local_ip4, 1) != 0) > return SK_DROP; > } > > /* Narrow loads from IPv6 fields */ > if (!v4) { > - /* Expenct non-:: IP in remote_ip6 */ > - byte = (__u8 *)&ctx->remote_ip6; > - if (byte[0] == 0 && byte[1] == 0 && > - byte[2] == 0 && byte[3] == 0 && > - byte[4] == 0 && byte[5] == 0 && > - byte[6] == 0 && byte[7] == 0 && > - byte[8] == 0 && byte[9] == 0 && > - byte[10] == 0 && byte[11] == 0 && > - byte[12] == 0 && byte[13] == 0 && > - byte[14] == 0 && byte[15] == 0) > + /* Expect non-:: IP in remote_ip6 */ > + if (LSB(ctx->remote_ip6[0], 0) == 0 && > + LSB(ctx->remote_ip6[0], 1) == 0 && > + LSB(ctx->remote_ip6[0], 2) == 0 && > + LSB(ctx->remote_ip6[0], 3) == 0 && > + LSB(ctx->remote_ip6[1], 0) == 0 && > + LSB(ctx->remote_ip6[1], 1) == 0 && > + LSB(ctx->remote_ip6[1], 2) == 0 && > + LSB(ctx->remote_ip6[1], 3) == 0 && > + LSB(ctx->remote_ip6[2], 0) == 0 && > + LSB(ctx->remote_ip6[2], 1) == 0 && > + LSB(ctx->remote_ip6[2], 2) == 0 && > + LSB(ctx->remote_ip6[2], 3) == 0 && > + LSB(ctx->remote_ip6[3], 0) == 0 && > + LSB(ctx->remote_ip6[3], 1) == 0 && > + LSB(ctx->remote_ip6[3], 2) == 0 && > + LSB(ctx->remote_ip6[3], 3) == 0) > return SK_DROP; > - half = (__u16 *)&ctx->remote_ip6; > - if (half[0] == 0 && half[1] == 0 && > - half[2] == 0 && half[3] == 0 && > - half[4] == 0 && half[5] == 0 && > - half[6] == 0 && half[7] == 0) > + if (LSW(ctx->remote_ip6[0], 0) == 0 && > + LSW(ctx->remote_ip6[0], 1) == 0 && > + LSW(ctx->remote_ip6[1], 0) == 0 && > + LSW(ctx->remote_ip6[1], 1) == 0 && > + LSW(ctx->remote_ip6[2], 0) == 0 && > + LSW(ctx->remote_ip6[2], 1) == 0 && > + LSW(ctx->remote_ip6[3], 0) == 0 && > + LSW(ctx->remote_ip6[3], 1) == 0) > return SK_DROP; > - > /* Expect DST_IP6 in local_ip6 */ > - byte = (__u8 *)&ctx->local_ip6; > - if (byte[0] != ((DST_IP6[0] >> 0) & 0xff) || > - byte[1] != ((DST_IP6[0] >> 8) & 0xff) || > - byte[2] != ((DST_IP6[0] >> 16) & 0xff) || > - byte[3] != ((DST_IP6[0] >> 24) & 0xff) || > - byte[4] != ((DST_IP6[1] >> 0) & 0xff) || > - byte[5] != ((DST_IP6[1] >> 8) & 0xff) || > - byte[6] != ((DST_IP6[1] >> 16) & 0xff) || > - byte[7] != ((DST_IP6[1] >> 24) & 0xff) || > - byte[8] != ((DST_IP6[2] >> 0) & 0xff) || > - byte[9] != ((DST_IP6[2] >> 8) & 0xff) || > - byte[10] != ((DST_IP6[2] >> 16) & 0xff) || > - byte[11] != ((DST_IP6[2] >> 24) & 0xff) || > - byte[12] != ((DST_IP6[3] >> 0) & 0xff) || > - byte[13] != ((DST_IP6[3] >> 8) & 0xff) || > - byte[14] != ((DST_IP6[3] >> 16) & 0xff) || > - byte[15] != ((DST_IP6[3] >> 24) & 0xff)) > + if (LSB(ctx->local_ip6[0], 0) != ((DST_IP6[0] >> 0) & 0xff) || > + LSB(ctx->local_ip6[0], 1) != ((DST_IP6[0] >> 8) & 0xff) || > + LSB(ctx->local_ip6[0], 2) != ((DST_IP6[0] >> 16) & 0xff) || > + LSB(ctx->local_ip6[0], 3) != ((DST_IP6[0] >> 24) & 0xff) || > + LSB(ctx->local_ip6[1], 0) != ((DST_IP6[1] >> 0) & 0xff) || > + LSB(ctx->local_ip6[1], 1) != ((DST_IP6[1] >> 8) & 0xff) || > + LSB(ctx->local_ip6[1], 2) != ((DST_IP6[1] >> 16) & 0xff) || > + LSB(ctx->local_ip6[1], 3) != ((DST_IP6[1] >> 24) & 0xff) || > + LSB(ctx->local_ip6[2], 0) != ((DST_IP6[2] >> 0) & 0xff) || > + LSB(ctx->local_ip6[2], 1) != ((DST_IP6[2] >> 8) & 0xff) || > + LSB(ctx->local_ip6[2], 2) != ((DST_IP6[2] >> 16) & 0xff) || > + LSB(ctx->local_ip6[2], 3) != ((DST_IP6[2] >> 24) & 0xff) || > + LSB(ctx->local_ip6[3], 0) != ((DST_IP6[3] >> 0) & 0xff) || > + LSB(ctx->local_ip6[3], 1) != ((DST_IP6[3] >> 8) & 0xff) || > + LSB(ctx->local_ip6[3], 2) != ((DST_IP6[3] >> 16) & 0xff) || > + LSB(ctx->local_ip6[3], 3) != ((DST_IP6[3] >> 24) & 0xff)) > return SK_DROP; > - half = (__u16 *)&ctx->local_ip6; > - if (half[0] != ((DST_IP6[0] >> 0) & 0xffff) || > - half[1] != ((DST_IP6[0] >> 16) & 0xffff) || > - half[2] != ((DST_IP6[1] >> 0) & 0xffff) || > - half[3] != ((DST_IP6[1] >> 16) & 0xffff) || > - half[4] != ((DST_IP6[2] >> 0) & 0xffff) || > - half[5] != ((DST_IP6[2] >> 16) & 0xffff) || > - half[6] != ((DST_IP6[3] >> 0) & 0xffff) || > - half[7] != ((DST_IP6[3] >> 16) & 0xffff)) > + if (LSW(ctx->local_ip6[0], 0) != ((DST_IP6[0] >> 0) & 0xffff) || > + LSW(ctx->local_ip6[0], 1) != > + ((DST_IP6[0] >> 16) & 0xffff) || > + LSW(ctx->local_ip6[1], 0) != ((DST_IP6[1] >> 0) & 0xffff) || > + LSW(ctx->local_ip6[1], 1) != > + ((DST_IP6[1] >> 16) & 0xffff) || > + LSW(ctx->local_ip6[2], 0) != ((DST_IP6[2] >> 0) & 0xffff) || > + LSW(ctx->local_ip6[2], 1) != > + ((DST_IP6[2] >> 16) & 0xffff) || > + LSW(ctx->local_ip6[3], 0) != ((DST_IP6[3] >> 0) & 0xffff) || > + LSW(ctx->local_ip6[3], 1) != ((DST_IP6[3] >> 16) & 0xffff)) > return SK_DROP; > } else { > /* Expect :: IPs when family != AF_INET6 */ > - byte = (__u8 *)&ctx->remote_ip6; > - if (byte[0] != 0 || byte[1] != 0 || > - byte[2] != 0 || byte[3] != 0 || > - byte[4] != 0 || byte[5] != 0 || > - byte[6] != 0 || byte[7] != 0 || > - byte[8] != 0 || byte[9] != 0 || > - byte[10] != 0 || byte[11] != 0 || > - byte[12] != 0 || byte[13] != 0 || > - byte[14] != 0 || byte[15] != 0) > + if (LSB(ctx->remote_ip6[0], 0) != 0 || > + LSB(ctx->remote_ip6[0], 1) != 0 || > + LSB(ctx->remote_ip6[0], 2) != 0 || > + LSB(ctx->remote_ip6[0], 3) != 0 || > + LSB(ctx->remote_ip6[1], 0) != 0 || > + LSB(ctx->remote_ip6[1], 1) != 0 || > + LSB(ctx->remote_ip6[1], 2) != 0 || > + LSB(ctx->remote_ip6[1], 3) != 0 || > + LSB(ctx->remote_ip6[2], 0) != 0 || > + LSB(ctx->remote_ip6[2], 1) != 0 || > + LSB(ctx->remote_ip6[2], 2) != 0 || > + LSB(ctx->remote_ip6[2], 3) != 0 || > + LSB(ctx->remote_ip6[3], 0) != 0 || > + LSB(ctx->remote_ip6[3], 1) != 0 || > + LSB(ctx->remote_ip6[3], 2) != 0 || > + LSB(ctx->remote_ip6[3], 3) != 0) > return SK_DROP; > - half = (__u16 *)&ctx->remote_ip6; > - if (half[0] != 0 || half[1] != 0 || > - half[2] != 0 || half[3] != 0 || > - half[4] != 0 || half[5] != 0 || > - half[6] != 0 || half[7] != 0) > + if (LSW(ctx->remote_ip6[0], 0) != 0 || > + LSW(ctx->remote_ip6[0], 1) != 0 || > + LSW(ctx->remote_ip6[1], 0) != 0 || > + LSW(ctx->remote_ip6[1], 1) != 0 || > + LSW(ctx->remote_ip6[2], 0) != 0 || > + LSW(ctx->remote_ip6[2], 1) != 0 || > + LSW(ctx->remote_ip6[3], 0) != 0 || > + LSW(ctx->remote_ip6[3], 1) != 0) > return SK_DROP; > > - byte = (__u8 *)&ctx->local_ip6; > - if (byte[0] != 0 || byte[1] != 0 || > - byte[2] != 0 || byte[3] != 0 || > - byte[4] != 0 || byte[5] != 0 || > - byte[6] != 0 || byte[7] != 0 || > - byte[8] != 0 || byte[9] != 0 || > - byte[10] != 0 || byte[11] != 0 || > - byte[12] != 0 || byte[13] != 0 || > - byte[14] != 0 || byte[15] != 0) > + if (LSB(ctx->local_ip6[0], 0) != 0 || > + LSB(ctx->local_ip6[0], 1) != 0 || > + LSB(ctx->local_ip6[0], 2) != 0 || > + LSB(ctx->local_ip6[0], 3) != 0 || > + LSB(ctx->local_ip6[1], 0) != 0 || > + LSB(ctx->local_ip6[1], 1) != 0 || > + LSB(ctx->local_ip6[1], 2) != 0 || > + LSB(ctx->local_ip6[1], 3) != 0 || > + LSB(ctx->local_ip6[2], 0) != 0 || > + LSB(ctx->local_ip6[2], 1) != 0 || > + LSB(ctx->local_ip6[2], 2) != 0 || > + LSB(ctx->local_ip6[2], 3) != 0 || > + LSB(ctx->local_ip6[3], 0) != 0 || > + LSB(ctx->local_ip6[3], 1) != 0 || > + LSB(ctx->local_ip6[3], 2) != 0 || > + LSB(ctx->local_ip6[3], 3) != 0) > return SK_DROP; > - half = (__u16 *)&ctx->local_ip6; > - if (half[0] != 0 || half[1] != 0 || > - half[2] != 0 || half[3] != 0 || > - half[4] != 0 || half[5] != 0 || > - half[6] != 0 || half[7] != 0) > + if (LSW(ctx->remote_ip6[0], 0) != 0 || > + LSW(ctx->remote_ip6[0], 1) != 0 || > + LSW(ctx->remote_ip6[1], 0) != 0 || > + LSW(ctx->remote_ip6[1], 1) != 0 || > + LSW(ctx->remote_ip6[2], 0) != 0 || > + LSW(ctx->remote_ip6[2], 1) != 0 || > + LSW(ctx->remote_ip6[3], 0) != 0 || > + LSW(ctx->remote_ip6[3], 1) != 0) > return SK_DROP; > } > > -- > 2.25.4 >