mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 09:04:39 +02:00
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>
This commit is contained in:
parent
74523c06ae
commit
0b51940729
|
|
@ -8725,6 +8725,54 @@ static enum bpf_dynptr_type dynptr_get_type(struct bpf_verifier_env *env,
|
|||
return state->stack[spi].spilled_ptr.dynptr.type;
|
||||
}
|
||||
|
||||
static int check_reg_const_str(struct bpf_verifier_env *env,
|
||||
struct bpf_reg_state *reg, u32 regno)
|
||||
{
|
||||
struct bpf_map *map = reg->map_ptr;
|
||||
int err;
|
||||
int map_off;
|
||||
u64 map_addr;
|
||||
char *str_ptr;
|
||||
|
||||
if (reg->type != PTR_TO_MAP_VALUE)
|
||||
return -EINVAL;
|
||||
|
||||
if (!bpf_map_is_rdonly(map)) {
|
||||
verbose(env, "R%d does not point to a readonly map'\n", regno);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if (!tnum_is_const(reg->var_off)) {
|
||||
verbose(env, "R%d is not a constant address'\n", regno);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if (!map->ops->map_direct_value_addr) {
|
||||
verbose(env, "no direct value access support for this map type\n");
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
err = check_map_access(env, regno, reg->off,
|
||||
map->value_size - reg->off, false,
|
||||
ACCESS_HELPER);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
map_off = reg->off + reg->var_off.value;
|
||||
err = map->ops->map_direct_value_addr(map, &map_addr, map_off);
|
||||
if (err) {
|
||||
verbose(env, "direct value access on string failed\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
str_ptr = (char *)(long)(map_addr);
|
||||
if (!strnchr(str_ptr + map_off, map->value_size - map_off, 0)) {
|
||||
verbose(env, "string is not zero-terminated\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
|
||||
struct bpf_call_arg_meta *meta,
|
||||
const struct bpf_func_proto *fn,
|
||||
|
|
@ -8969,44 +9017,9 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
|
|||
}
|
||||
case ARG_PTR_TO_CONST_STR:
|
||||
{
|
||||
struct bpf_map *map = reg->map_ptr;
|
||||
int map_off;
|
||||
u64 map_addr;
|
||||
char *str_ptr;
|
||||
|
||||
if (!bpf_map_is_rdonly(map)) {
|
||||
verbose(env, "R%d does not point to a readonly map'\n", regno);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if (!tnum_is_const(reg->var_off)) {
|
||||
verbose(env, "R%d is not a constant address'\n", regno);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if (!map->ops->map_direct_value_addr) {
|
||||
verbose(env, "no direct value access support for this map type\n");
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
err = check_map_access(env, regno, reg->off,
|
||||
map->value_size - reg->off, false,
|
||||
ACCESS_HELPER);
|
||||
err = check_reg_const_str(env, reg, regno);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
map_off = reg->off + reg->var_off.value;
|
||||
err = map->ops->map_direct_value_addr(map, &map_addr, map_off);
|
||||
if (err) {
|
||||
verbose(env, "direct value access on string failed\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
str_ptr = (char *)(long)(map_addr);
|
||||
if (!strnchr(str_ptr + map_off, map->value_size - map_off, 0)) {
|
||||
verbose(env, "string is not zero-terminated\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ARG_PTR_TO_KPTR:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user