bpf: Limit up to 512 bytes for bpf_global_percpu_ma allocation
authorYonghong Song <yonghong.song@linux.dev>
Fri, 22 Dec 2023 03:18:01 +0000 (19:18 -0800)
committerAlexei Starovoitov <ast@kernel.org>
Thu, 4 Jan 2024 05:08:26 +0000 (21:08 -0800)
For percpu data structure allocation with bpf_global_percpu_ma,
the maximum data size is 4K. But for a system with large
number of cpus, bigger data size (e.g., 2K, 4K) might consume
a lot of memory. For example, the percpu memory consumption
with unit size 2K and 1024 cpus will be 2K * 1K * 1k = 2GB
memory.

We should discourage such usage. Let us limit the maximum data
size to be 512 for bpf_global_percpu_ma allocation.

Acked-by: Hou Tao <houtao1@huawei.com>
Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
Link: https://lore.kernel.org/r/20231222031801.1290841-1-yonghong.song@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/verifier.c

index e9699a2cfe4f161c6e52c2f8d186a258b76ffaa1..d5f4ff1eb235df341a10d72780edf7701c7a2038 100644 (file)
@@ -195,6 +195,8 @@ struct bpf_verifier_stack_elem {
                                          POISON_POINTER_DELTA))
 #define BPF_MAP_PTR(X)         ((struct bpf_map *)((X) & ~BPF_MAP_PTR_UNPRIV))
 
+#define BPF_GLOBAL_PERCPU_MA_MAX_SIZE  512
+
 static int acquire_reference_state(struct bpf_verifier_env *env, int insn_idx);
 static int release_reference(struct bpf_verifier_env *env, int ref_obj_id);
 static void invalidate_non_owning_refs(struct bpf_verifier_env *env);
@@ -12160,6 +12162,12 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
                                }
 
                                if (meta.func_id == special_kfunc_list[KF_bpf_percpu_obj_new_impl]) {
+                                       if (ret_t->size > BPF_GLOBAL_PERCPU_MA_MAX_SIZE) {
+                                               verbose(env, "bpf_percpu_obj_new type size (%d) is greater than %d\n",
+                                                       ret_t->size, BPF_GLOBAL_PERCPU_MA_MAX_SIZE);
+                                               return -EINVAL;
+                                       }
+
                                        if (!bpf_global_percpu_ma_set) {
                                                mutex_lock(&bpf_percpu_ma_lock);
                                                if (!bpf_global_percpu_ma_set) {