selftests/bpf: Work around llvm stack overflow in crypto progs

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>
This commit is contained in:
Alexei Starovoitov 2026-06-15 00:17:58 -07:00
parent 4e7c52b178
commit e4287bf34f
2 changed files with 28 additions and 14 deletions

View File

@ -11,10 +11,19 @@
#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);

View File

@ -10,11 +10,20 @@
#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));