mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2026-01-27 12:47:24 +01:00
bpf: add btf_type_is_i{32,64} helpers
There are places in BPF code which check if a BTF type is an integer
of particular size. This code can be made simpler by using helpers.
Add new btf_type_is_i{32,64} helpers, and simplify code in a few
files. (Suggested by Eduard for a patch which copy-pasted such a
check [1].)
v1 -> v2:
* export less generic helpers (Eduard)
* make subject less generic than in [v1] (Eduard)
[1] https://lore.kernel.org/bpf/7edb47e73baa46705119a23c6bf4af26517a640f.camel@gmail.com/
[v1] https://lore.kernel.org/bpf/20250624193655.733050-1-a.s.protopopov@gmail.com/
Suggested-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Anton Protopopov <a.s.protopopov@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20250625151621.1000584-1-a.s.protopopov@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
0ed5f79987
commit
d83caf7c8d
|
|
@ -221,6 +221,8 @@ bool btf_is_vmlinux(const struct btf *btf);
|
|||
struct module *btf_try_get_module(const struct btf *btf);
|
||||
u32 btf_nr_types(const struct btf *btf);
|
||||
struct btf *btf_base_btf(const struct btf *btf);
|
||||
bool btf_type_is_i32(const struct btf_type *t);
|
||||
bool btf_type_is_i64(const struct btf_type *t);
|
||||
bool btf_member_is_reg_int(const struct btf *btf, const struct btf_type *s,
|
||||
const struct btf_member *m,
|
||||
u32 expected_offset, u32 expected_size);
|
||||
|
|
|
|||
|
|
@ -530,8 +530,6 @@ static int array_map_check_btf(const struct bpf_map *map,
|
|||
const struct btf_type *key_type,
|
||||
const struct btf_type *value_type)
|
||||
{
|
||||
u32 int_data;
|
||||
|
||||
/* One exception for keyless BTF: .bss/.data/.rodata map */
|
||||
if (btf_type_is_void(key_type)) {
|
||||
if (map->map_type != BPF_MAP_TYPE_ARRAY ||
|
||||
|
|
@ -544,14 +542,11 @@ static int array_map_check_btf(const struct bpf_map *map,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (BTF_INFO_KIND(key_type->info) != BTF_KIND_INT)
|
||||
return -EINVAL;
|
||||
|
||||
int_data = *(u32 *)(key_type + 1);
|
||||
/* bpf array can only take a u32 key. This check makes sure
|
||||
/*
|
||||
* Bpf array can only take a u32 key. This check makes sure
|
||||
* that the btf matches the attr used during map_create.
|
||||
*/
|
||||
if (BTF_INT_BITS(int_data) != 32 || BTF_INT_OFFSET(int_data))
|
||||
if (!btf_type_is_i32(key_type))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -722,13 +722,7 @@ int bpf_local_storage_map_check_btf(const struct bpf_map *map,
|
|||
const struct btf_type *key_type,
|
||||
const struct btf_type *value_type)
|
||||
{
|
||||
u32 int_data;
|
||||
|
||||
if (BTF_INFO_KIND(key_type->info) != BTF_KIND_INT)
|
||||
return -EINVAL;
|
||||
|
||||
int_data = *(u32 *)(key_type + 1);
|
||||
if (BTF_INT_BITS(int_data) != 32 || BTF_INT_OFFSET(int_data))
|
||||
if (!btf_type_is_i32(key_type))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -858,26 +858,37 @@ const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id)
|
|||
EXPORT_SYMBOL_GPL(btf_type_by_id);
|
||||
|
||||
/*
|
||||
* Regular int is not a bit field and it must be either
|
||||
* u8/u16/u32/u64 or __int128.
|
||||
* Check that the type @t is a regular int. This means that @t is not
|
||||
* a bit field and it has the same size as either of u8/u16/u32/u64
|
||||
* or __int128. If @expected_size is not zero, then size of @t should
|
||||
* be the same. A caller should already have checked that the type @t
|
||||
* is an integer.
|
||||
*/
|
||||
static bool btf_type_int_is_regular(const struct btf_type *t)
|
||||
static bool __btf_type_int_is_regular(const struct btf_type *t, size_t expected_size)
|
||||
{
|
||||
u8 nr_bits, nr_bytes;
|
||||
u32 int_data;
|
||||
u32 int_data = btf_type_int(t);
|
||||
u8 nr_bits = BTF_INT_BITS(int_data);
|
||||
u8 nr_bytes = BITS_ROUNDUP_BYTES(nr_bits);
|
||||
|
||||
int_data = btf_type_int(t);
|
||||
nr_bits = BTF_INT_BITS(int_data);
|
||||
nr_bytes = BITS_ROUNDUP_BYTES(nr_bits);
|
||||
if (BITS_PER_BYTE_MASKED(nr_bits) ||
|
||||
BTF_INT_OFFSET(int_data) ||
|
||||
(nr_bytes != sizeof(u8) && nr_bytes != sizeof(u16) &&
|
||||
nr_bytes != sizeof(u32) && nr_bytes != sizeof(u64) &&
|
||||
nr_bytes != (2 * sizeof(u64)))) {
|
||||
return false;
|
||||
return BITS_PER_BYTE_MASKED(nr_bits) == 0 &&
|
||||
BTF_INT_OFFSET(int_data) == 0 &&
|
||||
(nr_bytes <= 16 && is_power_of_2(nr_bytes)) &&
|
||||
(expected_size == 0 || nr_bytes == expected_size);
|
||||
}
|
||||
|
||||
return true;
|
||||
static bool btf_type_int_is_regular(const struct btf_type *t)
|
||||
{
|
||||
return __btf_type_int_is_regular(t, 0);
|
||||
}
|
||||
|
||||
bool btf_type_is_i32(const struct btf_type *t)
|
||||
{
|
||||
return btf_type_is_int(t) && __btf_type_int_is_regular(t, 4);
|
||||
}
|
||||
|
||||
bool btf_type_is_i64(const struct btf_type *t)
|
||||
{
|
||||
return btf_type_is_int(t) && __btf_type_int_is_regular(t, 8);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -394,17 +394,10 @@ static int cgroup_storage_check_btf(const struct bpf_map *map,
|
|||
if (!btf_member_is_reg_int(btf, key_type, m, offset, size))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
u32 int_data;
|
||||
|
||||
/*
|
||||
* Key is expected to be u64, which stores the cgroup_inode_id
|
||||
*/
|
||||
|
||||
if (BTF_INFO_KIND(key_type->info) != BTF_KIND_INT)
|
||||
return -EINVAL;
|
||||
|
||||
int_data = *(u32 *)(key_type + 1);
|
||||
if (BTF_INT_BITS(int_data) != 64 || BTF_INT_OFFSET(int_data))
|
||||
if (!btf_type_is_i64(key_type))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user