mirror of
https://github.com/torvalds/linux
synced 2024-10-15 15:59:15 +00:00
bpf: support multiple tags per argument
Add ability to iterate multiple decl_tag types pointed to the same function argument. Use this to support multiple __arg_xxx tags per global subprog argument. We leave btf_find_decl_tag_value() intact, but change its implementation to use a new btf_find_next_decl_tag() which can be straightforwardly used to find next BTF type ID of a matching btf_decl_tag type. btf_prepare_func_args() is switched from btf_find_decl_tag_value() to btf_find_next_decl_tag() to gain multiple tags per argument support. Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Acked-by: Eduard Zingerman <eddyz87@gmail.com> Link: https://lore.kernel.org/r/20240105000909.2818934-5-andrii@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
54c11ec493
commit
522bb2c1f8
|
@ -2472,6 +2472,8 @@ int btf_check_type_match(struct bpf_verifier_log *log, const struct bpf_prog *pr
|
|||
struct btf *btf, const struct btf_type *t);
|
||||
const char *btf_find_decl_tag_value(const struct btf *btf, const struct btf_type *pt,
|
||||
int comp_idx, const char *tag_key);
|
||||
int btf_find_next_decl_tag(const struct btf *btf, const struct btf_type *pt,
|
||||
int comp_idx, const char *tag_key, int last_id);
|
||||
|
||||
struct bpf_prog *bpf_prog_by_id(u32 id);
|
||||
struct bpf_link *bpf_link_by_id(u32 id);
|
||||
|
|
|
@ -3310,30 +3310,48 @@ static int btf_find_kptr(const struct btf *btf, const struct btf_type *t,
|
|||
return BTF_FIELD_FOUND;
|
||||
}
|
||||
|
||||
int btf_find_next_decl_tag(const struct btf *btf, const struct btf_type *pt,
|
||||
int comp_idx, const char *tag_key, int last_id)
|
||||
{
|
||||
int len = strlen(tag_key);
|
||||
int i, n;
|
||||
|
||||
for (i = last_id + 1, n = btf_nr_types(btf); i < n; i++) {
|
||||
const struct btf_type *t = btf_type_by_id(btf, i);
|
||||
|
||||
if (!btf_type_is_decl_tag(t))
|
||||
continue;
|
||||
if (pt != btf_type_by_id(btf, t->type))
|
||||
continue;
|
||||
if (btf_type_decl_tag(t)->component_idx != comp_idx)
|
||||
continue;
|
||||
if (strncmp(__btf_name_by_offset(btf, t->name_off), tag_key, len))
|
||||
continue;
|
||||
return i;
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
const char *btf_find_decl_tag_value(const struct btf *btf, const struct btf_type *pt,
|
||||
int comp_idx, const char *tag_key)
|
||||
{
|
||||
const char *value = NULL;
|
||||
int i;
|
||||
const struct btf_type *t;
|
||||
int len, id;
|
||||
|
||||
for (i = 1; i < btf_nr_types(btf); i++) {
|
||||
const struct btf_type *t = btf_type_by_id(btf, i);
|
||||
int len = strlen(tag_key);
|
||||
id = btf_find_next_decl_tag(btf, pt, comp_idx, tag_key, 0);
|
||||
if (id < 0)
|
||||
return ERR_PTR(id);
|
||||
|
||||
t = btf_type_by_id(btf, id);
|
||||
len = strlen(tag_key);
|
||||
value = __btf_name_by_offset(btf, t->name_off) + len;
|
||||
|
||||
/* Prevent duplicate entries for same type */
|
||||
id = btf_find_next_decl_tag(btf, pt, comp_idx, tag_key, id);
|
||||
if (id >= 0)
|
||||
return ERR_PTR(-EEXIST);
|
||||
|
||||
if (!btf_type_is_decl_tag(t))
|
||||
continue;
|
||||
if (pt != btf_type_by_id(btf, t->type) ||
|
||||
btf_type_decl_tag(t)->component_idx != comp_idx)
|
||||
continue;
|
||||
if (strncmp(__btf_name_by_offset(btf, t->name_off), tag_key, len))
|
||||
continue;
|
||||
/* Prevent duplicate entries for same type */
|
||||
if (value)
|
||||
return ERR_PTR(-EEXIST);
|
||||
value = __btf_name_by_offset(btf, t->name_off) + len;
|
||||
}
|
||||
if (!value)
|
||||
return ERR_PTR(-ENOENT);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -7032,20 +7050,16 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
|
|||
* Only PTR_TO_CTX and SCALAR are supported atm.
|
||||
*/
|
||||
for (i = 0; i < nargs; i++) {
|
||||
const char *tag;
|
||||
u32 tags = 0;
|
||||
int id = 0;
|
||||
|
||||
tag = btf_find_decl_tag_value(btf, fn_t, i, "arg:");
|
||||
if (IS_ERR(tag) && PTR_ERR(tag) == -ENOENT) {
|
||||
tag = NULL;
|
||||
} else if (IS_ERR(tag)) {
|
||||
bpf_log(log, "arg#%d type's tag fetching failure: %ld\n", i, PTR_ERR(tag));
|
||||
return PTR_ERR(tag);
|
||||
}
|
||||
/* 'arg:<tag>' decl_tag takes precedence over derivation of
|
||||
* register type from BTF type itself
|
||||
*/
|
||||
if (tag) {
|
||||
while ((id = btf_find_next_decl_tag(btf, fn_t, i, "arg:", id)) > 0) {
|
||||
const struct btf_type *tag_t = btf_type_by_id(btf, id);
|
||||
const char *tag = __btf_name_by_offset(btf, tag_t->name_off) + 4;
|
||||
|
||||
/* disallow arg tags in static subprogs */
|
||||
if (!is_global) {
|
||||
bpf_log(log, "arg#%d type tag is not supported in static functions\n", i);
|
||||
|
@ -7061,6 +7075,10 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
if (id != -ENOENT) {
|
||||
bpf_log(log, "arg#%d type tag fetching failure: %d\n", i, id);
|
||||
return id;
|
||||
}
|
||||
|
||||
t = btf_type_by_id(btf, args[i].type);
|
||||
while (btf_type_is_modifier(t))
|
||||
|
|
Loading…
Reference in a new issue