Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: teach verifier actual bounds of bpf_get_smp_processor_id() result

bpf_get_smp_processor_id() helper returns current CPU on which BPF
program runs. It can't return value that is bigger than maximum allowed
number of CPUs (minus one, due to zero indexing). Teach BPF verifier to
recognize that. This makes it possible to use bpf_get_smp_processor_id()
result to index into arrays without extra checks, as demonstrated in
subsequent selftests/bpf patch.

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20230711232400.1658562-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Andrii Nakryiko and committed by
Alexei Starovoitov
f42bcd16 87e098e6

+26 -11
+26 -11
kernel/bpf/verifier.c
··· 25 25 #include <linux/btf_ids.h> 26 26 #include <linux/poison.h> 27 27 #include <linux/module.h> 28 + #include <linux/cpumask.h> 28 29 29 30 #include "disasm.h" 30 31 ··· 9117 9116 { 9118 9117 struct bpf_reg_state *ret_reg = &regs[BPF_REG_0]; 9119 9118 9120 - if (ret_type != RET_INTEGER || 9121 - (func_id != BPF_FUNC_get_stack && 9122 - func_id != BPF_FUNC_get_task_stack && 9123 - func_id != BPF_FUNC_probe_read_str && 9124 - func_id != BPF_FUNC_probe_read_kernel_str && 9125 - func_id != BPF_FUNC_probe_read_user_str)) 9119 + if (ret_type != RET_INTEGER) 9126 9120 return; 9127 9121 9128 - ret_reg->smax_value = meta->msize_max_value; 9129 - ret_reg->s32_max_value = meta->msize_max_value; 9130 - ret_reg->smin_value = -MAX_ERRNO; 9131 - ret_reg->s32_min_value = -MAX_ERRNO; 9132 - reg_bounds_sync(ret_reg); 9122 + switch (func_id) { 9123 + case BPF_FUNC_get_stack: 9124 + case BPF_FUNC_get_task_stack: 9125 + case BPF_FUNC_probe_read_str: 9126 + case BPF_FUNC_probe_read_kernel_str: 9127 + case BPF_FUNC_probe_read_user_str: 9128 + ret_reg->smax_value = meta->msize_max_value; 9129 + ret_reg->s32_max_value = meta->msize_max_value; 9130 + ret_reg->smin_value = -MAX_ERRNO; 9131 + ret_reg->s32_min_value = -MAX_ERRNO; 9132 + reg_bounds_sync(ret_reg); 9133 + break; 9134 + case BPF_FUNC_get_smp_processor_id: 9135 + ret_reg->umax_value = nr_cpu_ids - 1; 9136 + ret_reg->u32_max_value = nr_cpu_ids - 1; 9137 + ret_reg->smax_value = nr_cpu_ids - 1; 9138 + ret_reg->s32_max_value = nr_cpu_ids - 1; 9139 + ret_reg->umin_value = 0; 9140 + ret_reg->u32_min_value = 0; 9141 + ret_reg->smin_value = 0; 9142 + ret_reg->s32_min_value = 0; 9143 + reg_bounds_sync(ret_reg); 9144 + break; 9145 + } 9133 9146 } 9134 9147 9135 9148 static int