#include <uapi/linux/btf.h>
#include <uapi/linux/bpf.h>
#include <uapi/linux/bpf_perf_event.h>
#include <uapi/linux/types.h>
#include <linux/seq_file.h>
#include <linux/compiler.h>
#include <linux/ctype.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/anon_inodes.h>
#include <linux/file.h>
#include <linux/uaccess.h>
#include <linux/kernel.h>
#include <linux/idr.h>
#include <linux/sort.h>
#include <linux/bpf_verifier.h>
#include <linux/btf.h>
#include <linux/btf_ids.h>
#include <linux/bpf.h>
#include <linux/bpf_lsm.h>
#include <linux/skmsg.h>
#include <linux/perf_event.h>
#include <linux/bsearch.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <net/netfilter/nf_bpf_link.h>
#include <net/sock.h>
#include <net/xdp.h>
#include "../tools/lib/bpf/relo_core.h"
#define BITS_PER_U128 …
#define BITS_PER_BYTE_MASK …
#define BITS_PER_BYTE_MASKED(bits) …
#define BITS_ROUNDDOWN_BYTES(bits) …
#define BITS_ROUNDUP_BYTES(bits) …
#define BTF_INFO_MASK …
#define BTF_INT_MASK …
#define BTF_TYPE_ID_VALID(type_id) …
#define BTF_STR_OFFSET_VALID(name_off) …
#define BTF_MAX_SIZE …
#define for_each_member_from(i, from, struct_type, member) …
#define for_each_vsi_from(i, from, struct_type, member) …
DEFINE_IDR(…);
DEFINE_SPINLOCK(…);
enum btf_kfunc_hook { … };
enum { … };
struct btf_kfunc_hook_filter { … };
struct btf_kfunc_set_tab { … };
struct btf_id_dtor_kfunc_tab { … };
struct btf_struct_ops_tab { … };
struct btf { … };
enum verifier_phase { … };
struct resolve_vertex { … };
enum visit_state { … };
enum resolve_mode { … };
#define MAX_RESOLVE_DEPTH …
struct btf_sec_info { … };
struct btf_verifier_env { … };
static const char * const btf_kind_str[NR_BTF_KINDS] = …;
const char *btf_type_str(const struct btf_type *t)
{ … }
#define BTF_SHOW_OBJ_SAFE_SIZE …
#define BTF_SHOW_OBJ_BASE_TYPE_SIZE …
#define BTF_SHOW_NAME_SIZE …
#define NOCAST_ALIAS_SUFFIX …
struct btf_show { … };
struct btf_kind_operations { … };
static const struct btf_kind_operations * const kind_ops[NR_BTF_KINDS];
static struct btf_type btf_void;
static int btf_resolve(struct btf_verifier_env *env,
const struct btf_type *t, u32 type_id);
static int btf_func_check(struct btf_verifier_env *env,
const struct btf_type *t);
static bool btf_type_is_modifier(const struct btf_type *t)
{ … }
bool btf_type_is_void(const struct btf_type *t)
{ … }
static bool btf_type_is_fwd(const struct btf_type *t)
{ … }
static bool btf_type_is_datasec(const struct btf_type *t)
{ … }
static bool btf_type_is_decl_tag(const struct btf_type *t)
{ … }
static bool btf_type_nosize(const struct btf_type *t)
{ … }
static bool btf_type_nosize_or_null(const struct btf_type *t)
{ … }
static bool btf_type_is_decl_tag_target(const struct btf_type *t)
{ … }
bool btf_is_vmlinux(const struct btf *btf)
{ … }
u32 btf_nr_types(const struct btf *btf)
{ … }
s32 btf_find_by_name_kind(const struct btf *btf, const char *name, u8 kind)
{ … }
s32 bpf_find_btf_id(const char *name, u32 kind, struct btf **btf_p)
{ … }
const struct btf_type *btf_type_skip_modifiers(const struct btf *btf,
u32 id, u32 *res_id)
{ … }
const struct btf_type *btf_type_resolve_ptr(const struct btf *btf,
u32 id, u32 *res_id)
{ … }
const struct btf_type *btf_type_resolve_func_ptr(const struct btf *btf,
u32 id, u32 *res_id)
{ … }
static bool btf_type_is_resolve_source_only(const struct btf_type *t)
{ … }
static bool btf_type_needs_resolve(const struct btf_type *t)
{ … }
static bool btf_type_has_size(const struct btf_type *t)
{ … }
static const char *btf_int_encoding_str(u8 encoding)
{ … }
static u32 btf_type_int(const struct btf_type *t)
{ … }
static const struct btf_array *btf_type_array(const struct btf_type *t)
{ … }
static const struct btf_enum *btf_type_enum(const struct btf_type *t)
{ … }
static const struct btf_var *btf_type_var(const struct btf_type *t)
{ … }
static const struct btf_decl_tag *btf_type_decl_tag(const struct btf_type *t)
{ … }
static const struct btf_enum64 *btf_type_enum64(const struct btf_type *t)
{ … }
static const struct btf_kind_operations *btf_type_ops(const struct btf_type *t)
{ … }
static bool btf_name_offset_valid(const struct btf *btf, u32 offset)
{ … }
static bool __btf_name_char_ok(char c, bool first)
{ … }
const char *btf_str_by_offset(const struct btf *btf, u32 offset)
{ … }
static bool __btf_name_valid(const struct btf *btf, u32 offset)
{ … }
static bool btf_name_valid_identifier(const struct btf *btf, u32 offset)
{ … }
static bool btf_name_valid_section(const struct btf *btf, u32 offset)
{ … }
static const char *__btf_name_by_offset(const struct btf *btf, u32 offset)
{ … }
const char *btf_name_by_offset(const struct btf *btf, u32 offset)
{ … }
const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id)
{ … }
EXPORT_SYMBOL_GPL(…);
static bool btf_type_int_is_regular(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)
{ … }
static const struct btf_type *btf_type_skip_qualifiers(const struct btf *btf,
u32 id)
{ … }
#define BTF_SHOW_MAX_ITER …
#define BTF_KIND_BIT(kind) …
static const char *btf_show_name(struct btf_show *show)
{ … }
static const char *__btf_show_indent(struct btf_show *show)
{ … }
static const char *btf_show_indent(struct btf_show *show)
{ … }
static const char *btf_show_newline(struct btf_show *show)
{ … }
static const char *btf_show_delim(struct btf_show *show)
{ … }
__printf(2, 3) static void btf_show(struct btf_show *show, const char *fmt, ...)
{ … }
#define btf_show_type_value(show, fmt, value) …
#define btf_show_type_values(show, fmt, ...) …
static int btf_show_obj_size_left(struct btf_show *show, void *data)
{ … }
static bool btf_show_obj_is_safe(struct btf_show *show, void *data, int size)
{ … }
static void *__btf_show_obj_safe(struct btf_show *show, void *data, int size)
{ … }
static void *btf_show_obj_safe(struct btf_show *show,
const struct btf_type *t,
void *data)
{ … }
static void *btf_show_start_type(struct btf_show *show,
const struct btf_type *t,
u32 type_id, void *data)
{ … }
static void btf_show_end_type(struct btf_show *show)
{ … }
static void *btf_show_start_aggr_type(struct btf_show *show,
const struct btf_type *t,
u32 type_id, void *data)
{ … }
static void btf_show_end_aggr_type(struct btf_show *show,
const char *suffix)
{ … }
static void btf_show_start_member(struct btf_show *show,
const struct btf_member *m)
{ … }
static void btf_show_start_array_member(struct btf_show *show)
{ … }
static void btf_show_end_member(struct btf_show *show)
{ … }
static void btf_show_end_array_member(struct btf_show *show)
{ … }
static void *btf_show_start_array_type(struct btf_show *show,
const struct btf_type *t,
u32 type_id,
u16 array_encoding,
void *data)
{ … }
static void btf_show_end_array_type(struct btf_show *show)
{ … }
static void *btf_show_start_struct_type(struct btf_show *show,
const struct btf_type *t,
u32 type_id,
void *data)
{ … }
static void btf_show_end_struct_type(struct btf_show *show)
{ … }
__printf(2, 3) static void __btf_verifier_log(struct bpf_verifier_log *log,
const char *fmt, ...)
{ … }
__printf(2, 3) static void btf_verifier_log(struct btf_verifier_env *env,
const char *fmt, ...)
{ … }
__printf(4, 5) static void __btf_verifier_log_type(struct btf_verifier_env *env,
const struct btf_type *t,
bool log_details,
const char *fmt, ...)
{ … }
#define btf_verifier_log_type(env, t, ...) …
#define btf_verifier_log_basic(env, t, ...) …
__printf(4, 5)
static void btf_verifier_log_member(struct btf_verifier_env *env,
const struct btf_type *struct_type,
const struct btf_member *member,
const char *fmt, ...)
{ … }
__printf(4, 5)
static void btf_verifier_log_vsi(struct btf_verifier_env *env,
const struct btf_type *datasec_type,
const struct btf_var_secinfo *vsi,
const char *fmt, ...)
{ … }
static void btf_verifier_log_hdr(struct btf_verifier_env *env,
u32 btf_data_size)
{ … }
static int btf_add_type(struct btf_verifier_env *env, struct btf_type *t)
{ … }
static int btf_alloc_id(struct btf *btf)
{ … }
static void btf_free_id(struct btf *btf)
{ … }
static void btf_free_kfunc_set_tab(struct btf *btf)
{ … }
static void btf_free_dtor_kfunc_tab(struct btf *btf)
{ … }
static void btf_struct_metas_free(struct btf_struct_metas *tab)
{ … }
static void btf_free_struct_meta_tab(struct btf *btf)
{ … }
static void btf_free_struct_ops_tab(struct btf *btf)
{ … }
static void btf_free(struct btf *btf)
{ … }
static void btf_free_rcu(struct rcu_head *rcu)
{ … }
const char *btf_get_name(const struct btf *btf)
{ … }
void btf_get(struct btf *btf)
{ … }
void btf_put(struct btf *btf)
{ … }
struct btf *btf_base_btf(const struct btf *btf)
{ … }
const struct btf_header *btf_header(const struct btf *btf)
{ … }
void btf_set_base_btf(struct btf *btf, const struct btf *base_btf)
{ … }
static int env_resolve_init(struct btf_verifier_env *env)
{ … }
static void btf_verifier_env_free(struct btf_verifier_env *env)
{ … }
static bool env_type_is_resolve_sink(const struct btf_verifier_env *env,
const struct btf_type *next_type)
{ … }
static bool env_type_is_resolved(const struct btf_verifier_env *env,
u32 type_id)
{ … }
static int env_stack_push(struct btf_verifier_env *env,
const struct btf_type *t, u32 type_id)
{ … }
static void env_stack_set_next_member(struct btf_verifier_env *env,
u16 next_member)
{ … }
static void env_stack_pop_resolved(struct btf_verifier_env *env,
u32 resolved_type_id,
u32 resolved_size)
{ … }
static const struct resolve_vertex *env_stack_peak(struct btf_verifier_env *env)
{ … }
static const struct btf_type *
__btf_resolve_size(const struct btf *btf, const struct btf_type *type,
u32 *type_size, const struct btf_type **elem_type,
u32 *elem_id, u32 *total_nelems, u32 *type_id)
{ … }
const struct btf_type *
btf_resolve_size(const struct btf *btf, const struct btf_type *type,
u32 *type_size)
{ … }
static u32 btf_resolved_type_id(const struct btf *btf, u32 type_id)
{ … }
static const struct btf_type *btf_type_id_resolve(const struct btf *btf,
u32 *type_id)
{ … }
static u32 btf_resolved_type_size(const struct btf *btf, u32 type_id)
{ … }
const struct btf_type *btf_type_id_size(const struct btf *btf,
u32 *type_id, u32 *ret_size)
{ … }
static int btf_df_check_member(struct btf_verifier_env *env,
const struct btf_type *struct_type,
const struct btf_member *member,
const struct btf_type *member_type)
{ … }
static int btf_df_check_kflag_member(struct btf_verifier_env *env,
const struct btf_type *struct_type,
const struct btf_member *member,
const struct btf_type *member_type)
{ … }
static int btf_generic_check_kflag_member(struct btf_verifier_env *env,
const struct btf_type *struct_type,
const struct btf_member *member,
const struct btf_type *member_type)
{ … }
static int btf_df_resolve(struct btf_verifier_env *env,
const struct resolve_vertex *v)
{ … }
static void btf_df_show(const struct btf *btf, const struct btf_type *t,
u32 type_id, void *data, u8 bits_offsets,
struct btf_show *show)
{ … }
static int btf_int_check_member(struct btf_verifier_env *env,
const struct btf_type *struct_type,
const struct btf_member *member,
const struct btf_type *member_type)
{ … }
static int btf_int_check_kflag_member(struct btf_verifier_env *env,
const struct btf_type *struct_type,
const struct btf_member *member,
const struct btf_type *member_type)
{ … }
static s32 btf_int_check_meta(struct btf_verifier_env *env,
const struct btf_type *t,
u32 meta_left)
{ … }
static void btf_int_log(struct btf_verifier_env *env,
const struct btf_type *t)
{ … }
static void btf_int128_print(struct btf_show *show, void *data)
{ … }
static void btf_int128_shift(u64 *print_num, u16 left_shift_bits,
u16 right_shift_bits)
{ … }
static void btf_bitfield_show(void *data, u8 bits_offset,
u8 nr_bits, struct btf_show *show)
{ … }
static void btf_int_bits_show(const struct btf *btf,
const struct btf_type *t,
void *data, u8 bits_offset,
struct btf_show *show)
{ … }
static void btf_int_show(const struct btf *btf, const struct btf_type *t,
u32 type_id, void *data, u8 bits_offset,
struct btf_show *show)
{ … }
static const struct btf_kind_operations int_ops = …;
static int btf_modifier_check_member(struct btf_verifier_env *env,
const struct btf_type *struct_type,
const struct btf_member *member,
const struct btf_type *member_type)
{ … }
static int btf_modifier_check_kflag_member(struct btf_verifier_env *env,
const struct btf_type *struct_type,
const struct btf_member *member,
const struct btf_type *member_type)
{ … }
static int btf_ptr_check_member(struct btf_verifier_env *env,
const struct btf_type *struct_type,
const struct btf_member *member,
const struct btf_type *member_type)
{ … }
static int btf_ref_type_check_meta(struct btf_verifier_env *env,
const struct btf_type *t,
u32 meta_left)
{ … }
static int btf_modifier_resolve(struct btf_verifier_env *env,
const struct resolve_vertex *v)
{ … }
static int btf_var_resolve(struct btf_verifier_env *env,
const struct resolve_vertex *v)
{ … }
static int btf_ptr_resolve(struct btf_verifier_env *env,
const struct resolve_vertex *v)
{ … }
static void btf_modifier_show(const struct btf *btf,
const struct btf_type *t,
u32 type_id, void *data,
u8 bits_offset, struct btf_show *show)
{ … }
static void btf_var_show(const struct btf *btf, const struct btf_type *t,
u32 type_id, void *data, u8 bits_offset,
struct btf_show *show)
{ … }
static void btf_ptr_show(const struct btf *btf, const struct btf_type *t,
u32 type_id, void *data, u8 bits_offset,
struct btf_show *show)
{ … }
static void btf_ref_type_log(struct btf_verifier_env *env,
const struct btf_type *t)
{ … }
static struct btf_kind_operations modifier_ops = …;
static struct btf_kind_operations ptr_ops = …;
static s32 btf_fwd_check_meta(struct btf_verifier_env *env,
const struct btf_type *t,
u32 meta_left)
{ … }
static void btf_fwd_type_log(struct btf_verifier_env *env,
const struct btf_type *t)
{ … }
static struct btf_kind_operations fwd_ops = …;
static int btf_array_check_member(struct btf_verifier_env *env,
const struct btf_type *struct_type,
const struct btf_member *member,
const struct btf_type *member_type)
{ … }
static s32 btf_array_check_meta(struct btf_verifier_env *env,
const struct btf_type *t,
u32 meta_left)
{ … }
static int btf_array_resolve(struct btf_verifier_env *env,
const struct resolve_vertex *v)
{ … }
static void btf_array_log(struct btf_verifier_env *env,
const struct btf_type *t)
{ … }
static void __btf_array_show(const struct btf *btf, const struct btf_type *t,
u32 type_id, void *data, u8 bits_offset,
struct btf_show *show)
{ … }
static void btf_array_show(const struct btf *btf, const struct btf_type *t,
u32 type_id, void *data, u8 bits_offset,
struct btf_show *show)
{ … }
static struct btf_kind_operations array_ops = …;
static int btf_struct_check_member(struct btf_verifier_env *env,
const struct btf_type *struct_type,
const struct btf_member *member,
const struct btf_type *member_type)
{ … }
static s32 btf_struct_check_meta(struct btf_verifier_env *env,
const struct btf_type *t,
u32 meta_left)
{ … }
static int btf_struct_resolve(struct btf_verifier_env *env,
const struct resolve_vertex *v)
{ … }
static void btf_struct_log(struct btf_verifier_env *env,
const struct btf_type *t)
{ … }
enum { … };
struct btf_field_info { … };
static int btf_find_struct(const struct btf *btf, const struct btf_type *t,
u32 off, int sz, enum btf_field_type field_type,
struct btf_field_info *info)
{ … }
static int btf_find_kptr(const struct btf *btf, const struct btf_type *t,
u32 off, int sz, struct btf_field_info *info)
{ … }
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)
{ … }
const char *btf_find_decl_tag_value(const struct btf *btf, const struct btf_type *pt,
int comp_idx, const char *tag_key)
{ … }
static int
btf_find_graph_root(const struct btf *btf, const struct btf_type *pt,
const struct btf_type *t, int comp_idx, u32 off,
int sz, struct btf_field_info *info,
enum btf_field_type head_type)
{ … }
#define field_mask_test_name …
static int btf_get_field_type(const struct btf *btf, const struct btf_type *var_type,
u32 field_mask, u32 *seen_mask,
int *align, int *sz)
{ … }
#undef field_mask_test_name
static int btf_repeat_fields(struct btf_field_info *info,
u32 field_cnt, u32 repeat_cnt, u32 elem_size)
{ … }
static int btf_find_struct_field(const struct btf *btf,
const struct btf_type *t, u32 field_mask,
struct btf_field_info *info, int info_cnt,
u32 level);
static int btf_find_nested_struct(const struct btf *btf, const struct btf_type *t,
u32 off, u32 nelems,
u32 field_mask, struct btf_field_info *info,
int info_cnt, u32 level)
{ … }
static int btf_find_field_one(const struct btf *btf,
const struct btf_type *var,
const struct btf_type *var_type,
int var_idx,
u32 off, u32 expected_size,
u32 field_mask, u32 *seen_mask,
struct btf_field_info *info, int info_cnt,
u32 level)
{ … }
static int btf_find_struct_field(const struct btf *btf,
const struct btf_type *t, u32 field_mask,
struct btf_field_info *info, int info_cnt,
u32 level)
{ … }
static int btf_find_datasec_var(const struct btf *btf, const struct btf_type *t,
u32 field_mask, struct btf_field_info *info,
int info_cnt, u32 level)
{ … }
static int btf_find_field(const struct btf *btf, const struct btf_type *t,
u32 field_mask, struct btf_field_info *info,
int info_cnt)
{ … }
static int btf_parse_kptr(const struct btf *btf, struct btf_field *field,
struct btf_field_info *info)
{ … }
static int btf_parse_graph_root(const struct btf *btf,
struct btf_field *field,
struct btf_field_info *info,
const char *node_type_name,
size_t node_type_align)
{ … }
static int btf_parse_list_head(const struct btf *btf, struct btf_field *field,
struct btf_field_info *info)
{ … }
static int btf_parse_rb_root(const struct btf *btf, struct btf_field *field,
struct btf_field_info *info)
{ … }
static int btf_field_cmp(const void *_a, const void *_b, const void *priv)
{ … }
struct btf_record *btf_parse_fields(const struct btf *btf, const struct btf_type *t,
u32 field_mask, u32 value_size)
{ … }
int btf_check_and_fixup_fields(const struct btf *btf, struct btf_record *rec)
{ … }
static void __btf_struct_show(const struct btf *btf, const struct btf_type *t,
u32 type_id, void *data, u8 bits_offset,
struct btf_show *show)
{ … }
static void btf_struct_show(const struct btf *btf, const struct btf_type *t,
u32 type_id, void *data, u8 bits_offset,
struct btf_show *show)
{ … }
static struct btf_kind_operations struct_ops = …;
static int btf_enum_check_member(struct btf_verifier_env *env,
const struct btf_type *struct_type,
const struct btf_member *member,
const struct btf_type *member_type)
{ … }
static int btf_enum_check_kflag_member(struct btf_verifier_env *env,
const struct btf_type *struct_type,
const struct btf_member *member,
const struct btf_type *member_type)
{ … }
static s32 btf_enum_check_meta(struct btf_verifier_env *env,
const struct btf_type *t,
u32 meta_left)
{ … }
static void btf_enum_log(struct btf_verifier_env *env,
const struct btf_type *t)
{ … }
static void btf_enum_show(const struct btf *btf, const struct btf_type *t,
u32 type_id, void *data, u8 bits_offset,
struct btf_show *show)
{ … }
static struct btf_kind_operations enum_ops = …;
static s32 btf_enum64_check_meta(struct btf_verifier_env *env,
const struct btf_type *t,
u32 meta_left)
{ … }
static void btf_enum64_show(const struct btf *btf, const struct btf_type *t,
u32 type_id, void *data, u8 bits_offset,
struct btf_show *show)
{ … }
static struct btf_kind_operations enum64_ops = …;
static s32 btf_func_proto_check_meta(struct btf_verifier_env *env,
const struct btf_type *t,
u32 meta_left)
{ … }
static void btf_func_proto_log(struct btf_verifier_env *env,
const struct btf_type *t)
{ … }
static struct btf_kind_operations func_proto_ops = …;
static s32 btf_func_check_meta(struct btf_verifier_env *env,
const struct btf_type *t,
u32 meta_left)
{ … }
static int btf_func_resolve(struct btf_verifier_env *env,
const struct resolve_vertex *v)
{ … }
static struct btf_kind_operations func_ops = …;
static s32 btf_var_check_meta(struct btf_verifier_env *env,
const struct btf_type *t,
u32 meta_left)
{ … }
static void btf_var_log(struct btf_verifier_env *env, const struct btf_type *t)
{ … }
static const struct btf_kind_operations var_ops = …;
static s32 btf_datasec_check_meta(struct btf_verifier_env *env,
const struct btf_type *t,
u32 meta_left)
{ … }
static int btf_datasec_resolve(struct btf_verifier_env *env,
const struct resolve_vertex *v)
{ … }
static void btf_datasec_log(struct btf_verifier_env *env,
const struct btf_type *t)
{ … }
static void btf_datasec_show(const struct btf *btf,
const struct btf_type *t, u32 type_id,
void *data, u8 bits_offset,
struct btf_show *show)
{ … }
static const struct btf_kind_operations datasec_ops = …;
static s32 btf_float_check_meta(struct btf_verifier_env *env,
const struct btf_type *t,
u32 meta_left)
{ … }
static int btf_float_check_member(struct btf_verifier_env *env,
const struct btf_type *struct_type,
const struct btf_member *member,
const struct btf_type *member_type)
{ … }
static void btf_float_log(struct btf_verifier_env *env,
const struct btf_type *t)
{ … }
static const struct btf_kind_operations float_ops = …;
static s32 btf_decl_tag_check_meta(struct btf_verifier_env *env,
const struct btf_type *t,
u32 meta_left)
{ … }
static int btf_decl_tag_resolve(struct btf_verifier_env *env,
const struct resolve_vertex *v)
{ … }
static void btf_decl_tag_log(struct btf_verifier_env *env, const struct btf_type *t)
{ … }
static const struct btf_kind_operations decl_tag_ops = …;
static int btf_func_proto_check(struct btf_verifier_env *env,
const struct btf_type *t)
{ … }
static int btf_func_check(struct btf_verifier_env *env,
const struct btf_type *t)
{ … }
static const struct btf_kind_operations * const kind_ops[NR_BTF_KINDS] = …;
static s32 btf_check_meta(struct btf_verifier_env *env,
const struct btf_type *t,
u32 meta_left)
{ … }
static int btf_check_all_metas(struct btf_verifier_env *env)
{ … }
static bool btf_resolve_valid(struct btf_verifier_env *env,
const struct btf_type *t,
u32 type_id)
{ … }
static int btf_resolve(struct btf_verifier_env *env,
const struct btf_type *t, u32 type_id)
{ … }
static int btf_check_all_types(struct btf_verifier_env *env)
{ … }
static int btf_parse_type_sec(struct btf_verifier_env *env)
{ … }
static int btf_parse_str_sec(struct btf_verifier_env *env)
{ … }
static const size_t btf_sec_info_offset[] = …;
static int btf_sec_info_cmp(const void *a, const void *b)
{ … }
static int btf_check_sec_info(struct btf_verifier_env *env,
u32 btf_data_size)
{ … }
static int btf_parse_hdr(struct btf_verifier_env *env)
{ … }
static const char *alloc_obj_fields[] = …;
static struct btf_struct_metas *
btf_parse_struct_metas(struct bpf_verifier_log *log, struct btf *btf)
{ … }
struct btf_struct_meta *btf_find_struct_meta(const struct btf *btf, u32 btf_id)
{ … }
static int btf_check_type_tags(struct btf_verifier_env *env,
struct btf *btf, int start_id)
{ … }
static int finalize_log(struct bpf_verifier_log *log, bpfptr_t uattr, u32 uattr_size)
{ … }
static struct btf *btf_parse(const union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
{ … }
extern char __start_BTF[];
extern char __stop_BTF[];
extern struct btf *btf_vmlinux;
#define BPF_MAP_TYPE …
#define BPF_LINK_TYPE …
static union { … } bpf_ctx_convert;
enum { … };
static u8 bpf_ctx_convert_map[] = …;
#undef BPF_MAP_TYPE
#undef BPF_LINK_TYPE
static const struct btf_type *find_canonical_prog_ctx_type(enum bpf_prog_type prog_type)
{ … }
static int find_kern_ctx_type_id(enum bpf_prog_type prog_type)
{ … }
bool btf_is_projection_of(const char *pname, const char *tname)
{ … }
bool btf_is_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
const struct btf_type *t, enum bpf_prog_type prog_type,
int arg)
{ … }
struct user_regs_struct;
struct user_pt_regs;
static int btf_validate_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
const struct btf_type *t, int arg,
enum bpf_prog_type prog_type,
enum bpf_attach_type attach_type)
{ … }
static int btf_translate_to_vmlinux(struct bpf_verifier_log *log,
struct btf *btf,
const struct btf_type *t,
enum bpf_prog_type prog_type,
int arg)
{ … }
int get_kern_ctx_btf_id(struct bpf_verifier_log *log, enum bpf_prog_type prog_type)
{ … }
BTF_ID_LIST(bpf_ctx_convert_btf_id)
BTF_ID(…)
static struct btf *btf_parse_base(struct btf_verifier_env *env, const char *name,
void *data, unsigned int data_size)
{ … }
struct btf *btf_parse_vmlinux(void)
{ … }
static __u32 btf_relocate_id(const struct btf *btf, __u32 id)
{ … }
#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
static struct btf *btf_parse_module(const char *module_name, const void *data,
unsigned int data_size, void *base_data,
unsigned int base_data_size)
{
struct btf *btf = NULL, *vmlinux_btf, *base_btf = NULL;
struct btf_verifier_env *env = NULL;
struct bpf_verifier_log *log;
int err = 0;
vmlinux_btf = bpf_get_btf_vmlinux();
if (IS_ERR(vmlinux_btf))
return vmlinux_btf;
if (!vmlinux_btf)
return ERR_PTR(-EINVAL);
env = kzalloc(sizeof(*env), GFP_KERNEL | __GFP_NOWARN);
if (!env)
return ERR_PTR(-ENOMEM);
log = &env->log;
log->level = BPF_LOG_KERNEL;
if (base_data) {
base_btf = btf_parse_base(env, ".BTF.base", base_data, base_data_size);
if (IS_ERR(base_btf)) {
err = PTR_ERR(base_btf);
goto errout;
}
} else {
base_btf = vmlinux_btf;
}
btf = kzalloc(sizeof(*btf), GFP_KERNEL | __GFP_NOWARN);
if (!btf) {
err = -ENOMEM;
goto errout;
}
env->btf = btf;
btf->base_btf = base_btf;
btf->start_id = base_btf->nr_types;
btf->start_str_off = base_btf->hdr.str_len;
btf->kernel_btf = true;
snprintf(btf->name, sizeof(btf->name), "%s", module_name);
btf->data = kvmalloc(data_size, GFP_KERNEL | __GFP_NOWARN);
if (!btf->data) {
err = -ENOMEM;
goto errout;
}
memcpy(btf->data, data, data_size);
btf->data_size = data_size;
err = btf_parse_hdr(env);
if (err)
goto errout;
btf->nohdr_data = btf->data + btf->hdr.hdr_len;
err = btf_parse_str_sec(env);
if (err)
goto errout;
err = btf_check_all_metas(env);
if (err)
goto errout;
err = btf_check_type_tags(env, btf, btf_nr_types(base_btf));
if (err)
goto errout;
if (base_btf != vmlinux_btf) {
err = btf_relocate(btf, vmlinux_btf, &btf->base_id_map);
if (err)
goto errout;
btf_free(base_btf);
base_btf = vmlinux_btf;
}
btf_verifier_env_free(env);
refcount_set(&btf->refcnt, 1);
return btf;
errout:
btf_verifier_env_free(env);
if (base_btf != vmlinux_btf)
btf_free(base_btf);
if (btf) {
kvfree(btf->data);
kvfree(btf->types);
kfree(btf);
}
return ERR_PTR(err);
}
#endif
struct btf *bpf_prog_get_target_btf(const struct bpf_prog *prog)
{ … }
static bool is_int_ptr(struct btf *btf, const struct btf_type *t)
{ … }
static u32 get_ctx_arg_idx(struct btf *btf, const struct btf_type *func_proto,
int off)
{ … }
static bool prog_args_trusted(const struct bpf_prog *prog)
{ … }
int btf_ctx_arg_offset(const struct btf *btf, const struct btf_type *func_proto,
u32 arg_no)
{ … }
bool btf_ctx_access(int off, int size, enum bpf_access_type type,
const struct bpf_prog *prog,
struct bpf_insn_access_aux *info)
{ … }
EXPORT_SYMBOL_GPL(…);
enum bpf_struct_walk_result { … };
static int btf_struct_walk(struct bpf_verifier_log *log, const struct btf *btf,
const struct btf_type *t, int off, int size,
u32 *next_btf_id, enum bpf_type_flag *flag,
const char **field_name)
{ … }
int btf_struct_access(struct bpf_verifier_log *log,
const struct bpf_reg_state *reg,
int off, int size, enum bpf_access_type atype __maybe_unused,
u32 *next_btf_id, enum bpf_type_flag *flag,
const char **field_name)
{ … }
bool btf_types_are_same(const struct btf *btf1, u32 id1,
const struct btf *btf2, u32 id2)
{ … }
bool btf_struct_ids_match(struct bpf_verifier_log *log,
const struct btf *btf, u32 id, int off,
const struct btf *need_btf, u32 need_type_id,
bool strict)
{ … }
static int __get_type_size(struct btf *btf, u32 btf_id,
const struct btf_type **ret_type)
{ … }
static u8 __get_type_fmodel_flags(const struct btf_type *t)
{ … }
int btf_distill_func_proto(struct bpf_verifier_log *log,
struct btf *btf,
const struct btf_type *func,
const char *tname,
struct btf_func_model *m)
{ … }
static int btf_check_func_type_match(struct bpf_verifier_log *log,
struct btf *btf1, const struct btf_type *t1,
struct btf *btf2, const struct btf_type *t2)
{ … }
int btf_check_type_match(struct bpf_verifier_log *log, const struct bpf_prog *prog,
struct btf *btf2, const struct btf_type *t2)
{ … }
static bool btf_is_dynptr_ptr(const struct btf *btf, const struct btf_type *t)
{ … }
struct bpf_cand_cache { … };
static DEFINE_MUTEX(cand_cache_mutex);
static struct bpf_cand_cache *
bpf_core_find_cands(struct bpf_core_ctx *ctx, u32 local_type_id);
static int btf_get_ptr_to_btf_id(struct bpf_verifier_log *log, int arg_idx,
const struct btf *btf, const struct btf_type *t)
{ … }
enum btf_arg_tag { … };
int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
{ … }
static void btf_type_show(const struct btf *btf, u32 type_id, void *obj,
struct btf_show *show)
{ … }
__printf(2, 0) static void btf_seq_show(struct btf_show *show, const char *fmt,
va_list args)
{ … }
int btf_type_seq_show_flags(const struct btf *btf, u32 type_id,
void *obj, struct seq_file *m, u64 flags)
{ … }
void btf_type_seq_show(const struct btf *btf, u32 type_id, void *obj,
struct seq_file *m)
{ … }
struct btf_show_snprintf { … };
__printf(2, 0) static void btf_snprintf_show(struct btf_show *show, const char *fmt,
va_list args)
{ … }
int btf_type_snprintf_show(const struct btf *btf, u32 type_id, void *obj,
char *buf, int len, u64 flags)
{ … }
#ifdef CONFIG_PROC_FS
static void bpf_btf_show_fdinfo(struct seq_file *m, struct file *filp)
{ … }
#endif
static int btf_release(struct inode *inode, struct file *filp)
{ … }
const struct file_operations btf_fops = …;
static int __btf_new_fd(struct btf *btf)
{ … }
int btf_new_fd(const union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
{ … }
struct btf *btf_get_by_fd(int fd)
{ … }
int btf_get_info_by_fd(const struct btf *btf,
const union bpf_attr *attr,
union bpf_attr __user *uattr)
{ … }
int btf_get_fd_by_id(u32 id)
{ … }
u32 btf_obj_id(const struct btf *btf)
{ … }
bool btf_is_kernel(const struct btf *btf)
{ … }
bool btf_is_module(const struct btf *btf)
{ … }
enum { … };
#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
struct btf_module {
struct list_head list;
struct module *module;
struct btf *btf;
struct bin_attribute *sysfs_attr;
int flags;
};
static LIST_HEAD(btf_modules);
static DEFINE_MUTEX(btf_module_mutex);
static ssize_t
btf_module_read(struct file *file, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t len)
{
const struct btf *btf = bin_attr->private;
memcpy(buf, btf->data + off, len);
return len;
}
static void purge_cand_cache(struct btf *btf);
static int btf_module_notify(struct notifier_block *nb, unsigned long op,
void *module)
{
struct btf_module *btf_mod, *tmp;
struct module *mod = module;
struct btf *btf;
int err = 0;
if (mod->btf_data_size == 0 ||
(op != MODULE_STATE_COMING && op != MODULE_STATE_LIVE &&
op != MODULE_STATE_GOING))
goto out;
switch (op) {
case MODULE_STATE_COMING:
btf_mod = kzalloc(sizeof(*btf_mod), GFP_KERNEL);
if (!btf_mod) {
err = -ENOMEM;
goto out;
}
btf = btf_parse_module(mod->name, mod->btf_data, mod->btf_data_size,
mod->btf_base_data, mod->btf_base_data_size);
if (IS_ERR(btf)) {
kfree(btf_mod);
if (!IS_ENABLED(CONFIG_MODULE_ALLOW_BTF_MISMATCH)) {
pr_warn("failed to validate module [%s] BTF: %ld\n",
mod->name, PTR_ERR(btf));
err = PTR_ERR(btf);
} else {
pr_warn_once("Kernel module BTF mismatch detected, BTF debug info may be unavailable for some modules\n");
}
goto out;
}
err = btf_alloc_id(btf);
if (err) {
btf_free(btf);
kfree(btf_mod);
goto out;
}
purge_cand_cache(NULL);
mutex_lock(&btf_module_mutex);
btf_mod->module = module;
btf_mod->btf = btf;
list_add(&btf_mod->list, &btf_modules);
mutex_unlock(&btf_module_mutex);
if (IS_ENABLED(CONFIG_SYSFS)) {
struct bin_attribute *attr;
attr = kzalloc(sizeof(*attr), GFP_KERNEL);
if (!attr)
goto out;
sysfs_bin_attr_init(attr);
attr->attr.name = btf->name;
attr->attr.mode = 0444;
attr->size = btf->data_size;
attr->private = btf;
attr->read = btf_module_read;
err = sysfs_create_bin_file(btf_kobj, attr);
if (err) {
pr_warn("failed to register module [%s] BTF in sysfs: %d\n",
mod->name, err);
kfree(attr);
err = 0;
goto out;
}
btf_mod->sysfs_attr = attr;
}
break;
case MODULE_STATE_LIVE:
mutex_lock(&btf_module_mutex);
list_for_each_entry_safe(btf_mod, tmp, &btf_modules, list) {
if (btf_mod->module != module)
continue;
btf_mod->flags |= BTF_MODULE_F_LIVE;
break;
}
mutex_unlock(&btf_module_mutex);
break;
case MODULE_STATE_GOING:
mutex_lock(&btf_module_mutex);
list_for_each_entry_safe(btf_mod, tmp, &btf_modules, list) {
if (btf_mod->module != module)
continue;
list_del(&btf_mod->list);
if (btf_mod->sysfs_attr)
sysfs_remove_bin_file(btf_kobj, btf_mod->sysfs_attr);
purge_cand_cache(btf_mod->btf);
btf_put(btf_mod->btf);
kfree(btf_mod->sysfs_attr);
kfree(btf_mod);
break;
}
mutex_unlock(&btf_module_mutex);
break;
}
out:
return notifier_from_errno(err);
}
static struct notifier_block btf_module_nb = {
.notifier_call = btf_module_notify,
};
static int __init btf_module_init(void)
{
register_module_notifier(&btf_module_nb);
return 0;
}
fs_initcall(btf_module_init);
#endif
struct module *btf_try_get_module(const struct btf *btf)
{ … }
static struct btf *btf_get_module_btf(const struct module *module)
{ … }
static int check_btf_kconfigs(const struct module *module, const char *feature)
{ … }
BPF_CALL_4(bpf_btf_find_by_name_kind, char *, name, int, name_sz, u32, kind, int, flags)
{ … }
const struct bpf_func_proto bpf_btf_find_by_name_kind_proto = …;
BTF_ID_LIST_GLOBAL(btf_tracing_ids, MAX_BTF_TRACING_TYPE)
#define BTF_TRACING_TYPE …
BTF_TRACING_TYPE_xxx
#undef BTF_TRACING_TYPE
static int btf_check_iter_kfuncs(struct btf *btf, const char *func_name,
const struct btf_type *func, u32 func_flags)
{ … }
static int btf_check_kfunc_protos(struct btf *btf, u32 func_id, u32 func_flags)
{ … }
static int btf_populate_kfunc_set(struct btf *btf, enum btf_kfunc_hook hook,
const struct btf_kfunc_id_set *kset)
{ … }
static u32 *__btf_kfunc_id_set_contains(const struct btf *btf,
enum btf_kfunc_hook hook,
u32 kfunc_btf_id,
const struct bpf_prog *prog)
{ … }
static int bpf_prog_type_to_kfunc_hook(enum bpf_prog_type prog_type)
{ … }
u32 *btf_kfunc_id_set_contains(const struct btf *btf,
u32 kfunc_btf_id,
const struct bpf_prog *prog)
{ … }
u32 *btf_kfunc_is_modify_return(const struct btf *btf, u32 kfunc_btf_id,
const struct bpf_prog *prog)
{ … }
static int __register_btf_kfunc_id_set(enum btf_kfunc_hook hook,
const struct btf_kfunc_id_set *kset)
{ … }
int register_btf_kfunc_id_set(enum bpf_prog_type prog_type,
const struct btf_kfunc_id_set *kset)
{ … }
EXPORT_SYMBOL_GPL(…);
int register_btf_fmodret_id_set(const struct btf_kfunc_id_set *kset)
{ … }
EXPORT_SYMBOL_GPL(…);
s32 btf_find_dtor_kfunc(struct btf *btf, u32 btf_id)
{ … }
static int btf_check_dtor_kfuncs(struct btf *btf, const struct btf_id_dtor_kfunc *dtors, u32 cnt)
{ … }
int register_btf_id_dtor_kfuncs(const struct btf_id_dtor_kfunc *dtors, u32 add_cnt,
struct module *owner)
{ … }
EXPORT_SYMBOL_GPL(…);
#define MAX_TYPES_ARE_COMPAT_DEPTH …
int bpf_core_types_are_compat(const struct btf *local_btf, __u32 local_id,
const struct btf *targ_btf, __u32 targ_id)
{ … }
#define MAX_TYPES_MATCH_DEPTH …
int bpf_core_types_match(const struct btf *local_btf, u32 local_id,
const struct btf *targ_btf, u32 targ_id)
{ … }
static bool bpf_core_is_flavor_sep(const char *s)
{ … }
size_t bpf_core_essential_name_len(const char *name)
{ … }
static void bpf_free_cands(struct bpf_cand_cache *cands)
{ … }
static void bpf_free_cands_from_cache(struct bpf_cand_cache *cands)
{ … }
#define VMLINUX_CAND_CACHE_SIZE …
static struct bpf_cand_cache *vmlinux_cand_cache[VMLINUX_CAND_CACHE_SIZE];
#define MODULE_CAND_CACHE_SIZE …
static struct bpf_cand_cache *module_cand_cache[MODULE_CAND_CACHE_SIZE];
static void __print_cand_cache(struct bpf_verifier_log *log,
struct bpf_cand_cache **cache,
int cache_size)
{ … }
static void print_cand_cache(struct bpf_verifier_log *log)
{ … }
static u32 hash_cands(struct bpf_cand_cache *cands)
{ … }
static struct bpf_cand_cache *check_cand_cache(struct bpf_cand_cache *cands,
struct bpf_cand_cache **cache,
int cache_size)
{ … }
static size_t sizeof_cands(int cnt)
{ … }
static struct bpf_cand_cache *populate_cand_cache(struct bpf_cand_cache *cands,
struct bpf_cand_cache **cache,
int cache_size)
{ … }
#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
static void __purge_cand_cache(struct btf *btf, struct bpf_cand_cache **cache,
int cache_size)
{
struct bpf_cand_cache *cc;
int i, j;
for (i = 0; i < cache_size; i++) {
cc = cache[i];
if (!cc)
continue;
if (!btf) {
bpf_free_cands_from_cache(cc);
cache[i] = NULL;
continue;
}
for (j = 0; j < cc->cnt; j++)
if (cc->cands[j].btf == btf) {
bpf_free_cands_from_cache(cc);
cache[i] = NULL;
break;
}
}
}
static void purge_cand_cache(struct btf *btf)
{
mutex_lock(&cand_cache_mutex);
__purge_cand_cache(btf, module_cand_cache, MODULE_CAND_CACHE_SIZE);
mutex_unlock(&cand_cache_mutex);
}
#endif
static struct bpf_cand_cache *
bpf_core_add_cands(struct bpf_cand_cache *cands, const struct btf *targ_btf,
int targ_start_id)
{ … }
static struct bpf_cand_cache *
bpf_core_find_cands(struct bpf_core_ctx *ctx, u32 local_type_id)
{ … }
int bpf_core_apply(struct bpf_core_ctx *ctx, const struct bpf_core_relo *relo,
int relo_idx, void *insn)
{ … }
bool btf_nested_type_is_trusted(struct bpf_verifier_log *log,
const struct bpf_reg_state *reg,
const char *field_name, u32 btf_id, const char *suffix)
{ … }
bool btf_type_ids_nocast_alias(struct bpf_verifier_log *log,
const struct btf *reg_btf, u32 reg_id,
const struct btf *arg_btf, u32 arg_id)
{ … }
#ifdef CONFIG_BPF_JIT
static int
btf_add_struct_ops(struct btf *btf, struct bpf_struct_ops *st_ops,
struct bpf_verifier_log *log)
{ … }
const struct bpf_struct_ops_desc *
bpf_struct_ops_find_value(struct btf *btf, u32 value_id)
{ … }
const struct bpf_struct_ops_desc *
bpf_struct_ops_find(struct btf *btf, u32 type_id)
{ … }
int __register_bpf_struct_ops(struct bpf_struct_ops *st_ops)
{ … }
EXPORT_SYMBOL_GPL(…);
#endif
bool btf_param_match_suffix(const struct btf *btf,
const struct btf_param *arg,
const char *suffix)
{ … }