From 4b77208477b17b0b9e9cf9aba01b79740cda1a8d Mon Sep 17 00:00:00 2001 From: Luis Gerhorst <gerhorst@cs.fau.de> Date: Thu, 21 Dec 2023 17:09:54 +0100 Subject: [PATCH] [DRAFT] bpf: Sysctl for spec. push_stack() with nospec_v1 (for loxilb) loxilb needs 64k jmp_seq when inserting nospec_v1 after 8k jmp_seq. [DRAFT] bpf: No spec. push_stack() after stack_size>limit/8 [DRAFT] bpf: Add sysctl for (spec_v1_)complexity_limit_jmp_seq --- include/linux/bpf.h | 2 ++ kernel/bpf/syscall.c | 16 ++++++++++++++++ kernel/bpf/verifier.c | 10 +++++++--- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 95459e959472..df8a260b1fc4 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -2053,7 +2053,9 @@ static inline bool bpf_allow_uninit_stack(void) return perfmon_capable(); } +extern int bpf_complexity_limit_jmp_seq; extern int bpf_spec_v1; +extern int bpf_spec_v1_complexity_limit_jmp_seq; extern int bpf_spec_v4; static inline bool bpf_bypass_spec_v1(void) diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index c8ce04d942be..4dfb7f225504 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -58,7 +58,9 @@ static DEFINE_SPINLOCK(link_idr_lock); int sysctl_unprivileged_bpf_disabled __read_mostly = IS_BUILTIN(CONFIG_BPF_UNPRIV_DEFAULT_OFF) ? 2 : 0; +int bpf_complexity_limit_jmp_seq = 8192; int bpf_spec_v1 = 0; +int bpf_spec_v1_complexity_limit_jmp_seq = 4096; int bpf_spec_v4 = 0; static const struct bpf_map_ops * const bpf_map_types[] = { @@ -5484,6 +5486,13 @@ static struct ctl_table bpf_syscall_table[] = { .mode = 0644, .proc_handler = bpf_stats_handler, }, + { + .procname = "bpf_complexity_limit_jmp_seq", + .data = &bpf_complexity_limit_jmp_seq, + .maxlen = sizeof(bpf_complexity_limit_jmp_seq), + .mode = 0644, + .proc_handler = proc_dointvec, + }, { .procname = "bpf_spec_v1", .data = &bpf_spec_v1, @@ -5493,6 +5502,13 @@ static struct ctl_table bpf_syscall_table[] = { /* .extra1 = SYSCTL_ZERO, */ /* .extra2 = SYSCTL_ONE, */ }, + { + .procname = "bpf_spec_v1_complexity_limit_jmp_seq", + .data = &bpf_spec_v1_complexity_limit_jmp_seq, + .maxlen = sizeof(bpf_spec_v1_complexity_limit_jmp_seq), + .mode = 0644, + .proc_handler = proc_dointvec, + }, { .procname = "bpf_spec_v4", .data = &bpf_spec_v4, diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index f50d3837914d..043be689adcd 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -178,7 +178,6 @@ struct bpf_verifier_stack_elem { u32 log_pos; }; -#define BPF_COMPLEXITY_LIMIT_JMP_SEQ 8192 #define BPF_COMPLEXITY_LIMIT_STATES 64 #define BPF_MAP_KEY_POISON (1ULL << 63) @@ -1829,6 +1828,11 @@ static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env, struct bpf_verifier_stack_elem *elem; int err; + if (!env->bypass_spec_v1 && cur->speculative && env->stack_size > bpf_spec_v1_complexity_limit_jmp_seq) { + verbose(env, "avoiding spec. push_stack()\n"); + return NULL; + } + elem = kzalloc(sizeof(struct bpf_verifier_stack_elem), GFP_KERNEL); if (!elem) goto err; @@ -1843,7 +1847,7 @@ static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env, if (err) goto err; elem->st.speculative |= speculative; - if (env->stack_size > BPF_COMPLEXITY_LIMIT_JMP_SEQ) { + if (env->stack_size > bpf_complexity_limit_jmp_seq) { verbose(env, "The sequence of %d jumps is too complex.\n", env->stack_size); goto err; @@ -2375,7 +2379,7 @@ static struct bpf_verifier_state *push_async_cb(struct bpf_verifier_env *env, elem->log_pos = env->log.end_pos; env->head = elem; env->stack_size++; - if (env->stack_size > BPF_COMPLEXITY_LIMIT_JMP_SEQ) { + if (env->stack_size > bpf_complexity_limit_jmp_seq) { verbose(env, "The sequence of %d jumps is too complex for async cb.\n", env->stack_size); -- GitLab