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

bpf: Factor out helper check_reg_const_str()

ARG_PTR_TO_CONST_STR is used to specify constant string args for BPF
helpers. The logic that verifies a reg is ARG_PTR_TO_CONST_STR is
implemented in check_func_arg().

As we introduce kfuncs with constant string args, it is necessary to
do the same check for kfuncs (in check_kfunc_args). Factor out the logic
for ARG_PTR_TO_CONST_STR to a new check_reg_const_str() so that it can be
reused.

check_func_arg() ensures check_reg_const_str() is only called with reg of
type PTR_TO_MAP_VALUE. Add a redundent type check in check_reg_const_str()
to avoid misuse in the future. Other than this redundent check, there is
no change in behavior.

Signed-off-by: Song Liu <song@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Link: https://lore.kernel.org/bpf/20231107045725.2278852-3-song@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Song Liu and committed by
Alexei Starovoitov
0b519407 74523c06

+49 -36
+49 -36
kernel/bpf/verifier.c
··· 8725 8725 return state->stack[spi].spilled_ptr.dynptr.type; 8726 8726 } 8727 8727 8728 + static int check_reg_const_str(struct bpf_verifier_env *env, 8729 + struct bpf_reg_state *reg, u32 regno) 8730 + { 8731 + struct bpf_map *map = reg->map_ptr; 8732 + int err; 8733 + int map_off; 8734 + u64 map_addr; 8735 + char *str_ptr; 8736 + 8737 + if (reg->type != PTR_TO_MAP_VALUE) 8738 + return -EINVAL; 8739 + 8740 + if (!bpf_map_is_rdonly(map)) { 8741 + verbose(env, "R%d does not point to a readonly map'\n", regno); 8742 + return -EACCES; 8743 + } 8744 + 8745 + if (!tnum_is_const(reg->var_off)) { 8746 + verbose(env, "R%d is not a constant address'\n", regno); 8747 + return -EACCES; 8748 + } 8749 + 8750 + if (!map->ops->map_direct_value_addr) { 8751 + verbose(env, "no direct value access support for this map type\n"); 8752 + return -EACCES; 8753 + } 8754 + 8755 + err = check_map_access(env, regno, reg->off, 8756 + map->value_size - reg->off, false, 8757 + ACCESS_HELPER); 8758 + if (err) 8759 + return err; 8760 + 8761 + map_off = reg->off + reg->var_off.value; 8762 + err = map->ops->map_direct_value_addr(map, &map_addr, map_off); 8763 + if (err) { 8764 + verbose(env, "direct value access on string failed\n"); 8765 + return err; 8766 + } 8767 + 8768 + str_ptr = (char *)(long)(map_addr); 8769 + if (!strnchr(str_ptr + map_off, map->value_size - map_off, 0)) { 8770 + verbose(env, "string is not zero-terminated\n"); 8771 + return -EINVAL; 8772 + } 8773 + return 0; 8774 + } 8775 + 8728 8776 static int check_func_arg(struct bpf_verifier_env *env, u32 arg, 8729 8777 struct bpf_call_arg_meta *meta, 8730 8778 const struct bpf_func_proto *fn, ··· 9017 8969 } 9018 8970 case ARG_PTR_TO_CONST_STR: 9019 8971 { 9020 - struct bpf_map *map = reg->map_ptr; 9021 - int map_off; 9022 - u64 map_addr; 9023 - char *str_ptr; 9024 - 9025 - if (!bpf_map_is_rdonly(map)) { 9026 - verbose(env, "R%d does not point to a readonly map'\n", regno); 9027 - return -EACCES; 9028 - } 9029 - 9030 - if (!tnum_is_const(reg->var_off)) { 9031 - verbose(env, "R%d is not a constant address'\n", regno); 9032 - return -EACCES; 9033 - } 9034 - 9035 - if (!map->ops->map_direct_value_addr) { 9036 - verbose(env, "no direct value access support for this map type\n"); 9037 - return -EACCES; 9038 - } 9039 - 9040 - err = check_map_access(env, regno, reg->off, 9041 - map->value_size - reg->off, false, 9042 - ACCESS_HELPER); 8972 + err = check_reg_const_str(env, reg, regno); 9043 8973 if (err) 9044 8974 return err; 9045 - 9046 - map_off = reg->off + reg->var_off.value; 9047 - err = map->ops->map_direct_value_addr(map, &map_addr, map_off); 9048 - if (err) { 9049 - verbose(env, "direct value access on string failed\n"); 9050 - return err; 9051 - } 9052 - 9053 - str_ptr = (char *)(long)(map_addr); 9054 - if (!strnchr(str_ptr + map_off, map->value_size - map_off, 0)) { 9055 - verbose(env, "string is not zero-terminated\n"); 9056 - return -EINVAL; 9057 - } 9058 8975 break; 9059 8976 } 9060 8977 case ARG_PTR_TO_KPTR: