]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
selftests/bpf: Work around llvm stack overflow in crypto progs
authorAlexei Starovoitov <ast@kernel.org>
Mon, 15 Jun 2026 07:17:58 +0000 (00:17 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Mon, 15 Jun 2026 07:19:44 +0000 (00:19 -0700)
clang 23 fails to build crypto_bench.c and crypto_sanity.c with
"BPF stack limit exceeded". The progs fill a 408-byte
bpf_crypto_params on the stack and pass it to bpf_crypto_ctx_create().
clang 23 copies the byte-aligned cipher/key globals into it one byte at
a time through the stack, and keeps more than one copy of the struct
around. Together that blows the 512-byte limit.

Align the source arrays to 8 bytes so the copy is word-wise, and move
params off the stack into a static .bss var. static keeps it out of the
skeleton, where bpf_crypto_params is an incomplete type. Either change
alone is not enough.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/progs/crypto_bench.c
tools/testing/selftests/bpf/progs/crypto_sanity.c

index 4ac956b26240dc2cd39fbacaac63da9f7f13b72e..4c0a09aa1e6c1354f26962e63d0ce4c4804ca97c 100644 (file)
 #include "crypto_common.h"
 
 const volatile unsigned int len = 16;
-char cipher[128] = {};
+/*
+ * cipher[] and key[] are 8-byte aligned and 'params' is kept off the stack to
+ * work around an LLVM code generation bug. clang lowers the memcpy() of these
+ * byte-aligned globals into a per-byte load/store sequence staged on the stack,
+ * and additionally materializes the on-stack 'struct bpf_crypto_params' twice.
+ * Both blow the 512-byte BPF stack limit. Aligning the sources lets clang copy
+ * word-wise, and a global 'params' removes the large object from the stack.
+ */
+char cipher[128] __attribute__((aligned(8))) = {};
 u32 key_len, authsize;
 char dst[256] = {};
-u8 key[256] = {};
+u8 key[256] __attribute__((aligned(8))) = {};
+static struct bpf_crypto_params params;
 long hits = 0;
 int status;
 
@@ -22,11 +31,6 @@ SEC("syscall")
 int crypto_setup(void *args)
 {
        struct bpf_crypto_ctx *cctx;
-       struct bpf_crypto_params params = {
-               .type = "skcipher",
-               .key_len = key_len,
-               .authsize = authsize,
-       };
        int err = 0;
 
        status = 0;
@@ -36,6 +40,9 @@ int crypto_setup(void *args)
                return 0;
        }
 
+       __builtin_memcpy(&params.type, "skcipher", sizeof("skcipher"));
+       params.key_len = key_len;
+       params.authsize = authsize;
        __builtin_memcpy(&params.algo, cipher, sizeof(cipher));
        __builtin_memcpy(&params.key, key, sizeof(key));
        cctx = bpf_crypto_ctx_create(&params, sizeof(params), &err);
index dfd8a258f14a886ecc4e3df7d37f9998e1dbaa22..e81f5ac3b1aec17e296bc2110e790306f44d4eb1 100644 (file)
 #include "bpf_kfuncs.h"
 #include "crypto_common.h"
 
-unsigned char key[256] = {};
+/*
+ * key[] and algo[] are 8-byte aligned and 'params' is kept off the stack to
+ * work around an LLVM code generation bug. clang lowers the memcpy() of these
+ * byte-aligned globals into a per-byte load/store sequence staged on the stack,
+ * and additionally materializes the on-stack 'struct bpf_crypto_params' twice.
+ * Both blow the 512-byte BPF stack limit. Aligning the sources lets clang copy
+ * word-wise, and a global 'params' removes the large object from the stack.
+ */
+unsigned char key[256] __attribute__((aligned(8))) = {};
 u16 udp_test_port = 7777;
 u32 authsize, key_len;
-char algo[128] = {};
+char algo[128] __attribute__((aligned(8))) = {};
 char dst[16] = {}, dst_bad[8] = {};
+static struct bpf_crypto_params params;
 int status;
 
 static int skb_dynptr_validate(struct __sk_buff *skb, struct bpf_dynptr *psrc)
@@ -53,11 +62,6 @@ static int skb_dynptr_validate(struct __sk_buff *skb, struct bpf_dynptr *psrc)
 SEC("syscall")
 int skb_crypto_setup(void *ctx)
 {
-       struct bpf_crypto_params params = {
-               .type = "skcipher",
-               .key_len = key_len,
-               .authsize = authsize,
-       };
        struct bpf_crypto_ctx *cctx;
        int err;
 
@@ -67,6 +71,9 @@ int skb_crypto_setup(void *ctx)
                return 0;
        }
 
+       __builtin_memcpy(&params.type, "skcipher", sizeof("skcipher"));
+       params.key_len = key_len;
+       params.authsize = authsize;
        __builtin_memcpy(&params.algo, algo, sizeof(algo));
        __builtin_memcpy(&params.key, key, sizeof(key));