selftests/bpf: Fix bind program for big endian systems
authorJordan Rife <jrife@google.com>
Mon, 29 Apr 2024 21:45:18 +0000 (16:45 -0500)
committerMartin KaFai Lau <martin.lau@kernel.org>
Thu, 2 May 2024 19:09:22 +0000 (12:09 -0700)
Without this fix, the bind4 and bind6 programs will reject bind attempts
on big endian systems. This patch ensures that CI tests pass for the
s390x architecture.

Signed-off-by: Jordan Rife <jrife@google.com>
Link: https://lore.kernel.org/r/20240429214529.2644801-2-jrife@google.com
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
tools/testing/selftests/bpf/progs/bind4_prog.c
tools/testing/selftests/bpf/progs/bind6_prog.c
tools/testing/selftests/bpf/progs/bind_prog.h [new file with mode: 0644]

index a487f60b73ac49ff6e54faf346e80311a176e6f8..66005c1a5b367c39ed52c9df1efd05d9849f72af 100644 (file)
@@ -12,6 +12,8 @@
 #include <bpf/bpf_helpers.h>
 #include <bpf/bpf_endian.h>
 
+#include "bind_prog.h"
+
 #define SERV4_IP               0xc0a801feU /* 192.168.1.254 */
 #define SERV4_PORT             4040
 #define SERV4_REWRITE_IP       0x7f000001U /* 127.0.0.1 */
@@ -118,23 +120,23 @@ int bind_v4_prog(struct bpf_sock_addr *ctx)
 
        // u8 narrow loads:
        user_ip4 = 0;
-       user_ip4 |= ((volatile __u8 *)&ctx->user_ip4)[0] << 0;
-       user_ip4 |= ((volatile __u8 *)&ctx->user_ip4)[1] << 8;
-       user_ip4 |= ((volatile __u8 *)&ctx->user_ip4)[2] << 16;
-       user_ip4 |= ((volatile __u8 *)&ctx->user_ip4)[3] << 24;
+       user_ip4 |= load_byte(ctx->user_ip4, 0, sizeof(user_ip4));
+       user_ip4 |= load_byte(ctx->user_ip4, 1, sizeof(user_ip4));
+       user_ip4 |= load_byte(ctx->user_ip4, 2, sizeof(user_ip4));
+       user_ip4 |= load_byte(ctx->user_ip4, 3, sizeof(user_ip4));
        if (ctx->user_ip4 != user_ip4)
                return 0;
 
        user_port = 0;
-       user_port |= ((volatile __u8 *)&ctx->user_port)[0] << 0;
-       user_port |= ((volatile __u8 *)&ctx->user_port)[1] << 8;
+       user_port |= load_byte(ctx->user_port, 0, sizeof(user_port));
+       user_port |= load_byte(ctx->user_port, 1, sizeof(user_port));
        if (ctx->user_port != user_port)
                return 0;
 
        // u16 narrow loads:
        user_ip4 = 0;
-       user_ip4 |= ((volatile __u16 *)&ctx->user_ip4)[0] << 0;
-       user_ip4 |= ((volatile __u16 *)&ctx->user_ip4)[1] << 16;
+       user_ip4 |= load_word(ctx->user_ip4, 0, sizeof(user_ip4));
+       user_ip4 |= load_word(ctx->user_ip4, 1, sizeof(user_ip4));
        if (ctx->user_ip4 != user_ip4)
                return 0;
 
index d62cd9e9cf0eafe45ef6d77de7fb6f0638f8a5f7..9c86c712348cf58a96213312158f57ad72b96d0f 100644 (file)
@@ -12,6 +12,8 @@
 #include <bpf/bpf_helpers.h>
 #include <bpf/bpf_endian.h>
 
+#include "bind_prog.h"
+
 #define SERV6_IP_0             0xfaceb00c /* face:b00c:1234:5678::abcd */
 #define SERV6_IP_1             0x12345678
 #define SERV6_IP_2             0x00000000
@@ -129,25 +131,25 @@ int bind_v6_prog(struct bpf_sock_addr *ctx)
        // u8 narrow loads:
        for (i = 0; i < 4; i++) {
                user_ip6 = 0;
-               user_ip6 |= ((volatile __u8 *)&ctx->user_ip6[i])[0] << 0;
-               user_ip6 |= ((volatile __u8 *)&ctx->user_ip6[i])[1] << 8;
-               user_ip6 |= ((volatile __u8 *)&ctx->user_ip6[i])[2] << 16;
-               user_ip6 |= ((volatile __u8 *)&ctx->user_ip6[i])[3] << 24;
+               user_ip6 |= load_byte(ctx->user_ip6[i], 0, sizeof(user_ip6));
+               user_ip6 |= load_byte(ctx->user_ip6[i], 1, sizeof(user_ip6));
+               user_ip6 |= load_byte(ctx->user_ip6[i], 2, sizeof(user_ip6));
+               user_ip6 |= load_byte(ctx->user_ip6[i], 3, sizeof(user_ip6));
                if (ctx->user_ip6[i] != user_ip6)
                        return 0;
        }
 
        user_port = 0;
-       user_port |= ((volatile __u8 *)&ctx->user_port)[0] << 0;
-       user_port |= ((volatile __u8 *)&ctx->user_port)[1] << 8;
+       user_port |= load_byte(ctx->user_port, 0, sizeof(user_port));
+       user_port |= load_byte(ctx->user_port, 1, sizeof(user_port));
        if (ctx->user_port != user_port)
                return 0;
 
        // u16 narrow loads:
        for (i = 0; i < 4; i++) {
                user_ip6 = 0;
-               user_ip6 |= ((volatile __u16 *)&ctx->user_ip6[i])[0] << 0;
-               user_ip6 |= ((volatile __u16 *)&ctx->user_ip6[i])[1] << 16;
+               user_ip6 |= load_word(ctx->user_ip6[i], 0, sizeof(user_ip6));
+               user_ip6 |= load_word(ctx->user_ip6[i], 1, sizeof(user_ip6));
                if (ctx->user_ip6[i] != user_ip6)
                        return 0;
        }
diff --git a/tools/testing/selftests/bpf/progs/bind_prog.h b/tools/testing/selftests/bpf/progs/bind_prog.h
new file mode 100644 (file)
index 0000000..e830caa
--- /dev/null
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __BIND_PROG_H__
+#define __BIND_PROG_H__
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define load_byte(src, b, s) \
+       (((volatile __u8 *)&(src))[b] << 8 * b)
+#define load_word(src, w, s) \
+       (((volatile __u16 *)&(src))[w] << 16 * w)
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define load_byte(src, b, s) \
+       (((volatile __u8 *)&(src))[(b) + (sizeof(src) - (s))] << 8 * ((s) - (b) - 1))
+#define load_word(src, w, s) \
+       (((volatile __u16 *)&(src))[w] << 16 * (((s) / 2) - (w) - 1))
+#else
+# error "Fix your compiler's __BYTE_ORDER__?!"
+#endif
+
+#endif