@@ -6798,10 +6798,113 @@ int register_btf_kfunc_id_set(enum bpf_prog_type prog_type,
67986798}
67996799EXPORT_SYMBOL_GPL (register_btf_kfunc_id_set );
68006800
6801+ #define MAX_TYPES_ARE_COMPAT_DEPTH 2
6802+
6803+ static
6804+ int __bpf_core_types_are_compat (const struct btf * local_btf , __u32 local_id ,
6805+ const struct btf * targ_btf , __u32 targ_id ,
6806+ int level )
6807+ {
6808+ const struct btf_type * local_type , * targ_type ;
6809+ int depth = 32 ; /* max recursion depth */
6810+
6811+ /* caller made sure that names match (ignoring flavor suffix) */
6812+ local_type = btf_type_by_id (local_btf , local_id );
6813+ targ_type = btf_type_by_id (targ_btf , targ_id );
6814+ if (btf_kind (local_type ) != btf_kind (targ_type ))
6815+ return 0 ;
6816+
6817+ recur :
6818+ depth -- ;
6819+ if (depth < 0 )
6820+ return - EINVAL ;
6821+
6822+ local_type = btf_type_skip_modifiers (local_btf , local_id , & local_id );
6823+ targ_type = btf_type_skip_modifiers (targ_btf , targ_id , & targ_id );
6824+ if (!local_type || !targ_type )
6825+ return - EINVAL ;
6826+
6827+ if (btf_kind (local_type ) != btf_kind (targ_type ))
6828+ return 0 ;
6829+
6830+ switch (btf_kind (local_type )) {
6831+ case BTF_KIND_UNKN :
6832+ case BTF_KIND_STRUCT :
6833+ case BTF_KIND_UNION :
6834+ case BTF_KIND_ENUM :
6835+ case BTF_KIND_FWD :
6836+ return 1 ;
6837+ case BTF_KIND_INT :
6838+ /* just reject deprecated bitfield-like integers; all other
6839+ * integers are by default compatible between each other
6840+ */
6841+ return btf_int_offset (local_type ) == 0 && btf_int_offset (targ_type ) == 0 ;
6842+ case BTF_KIND_PTR :
6843+ local_id = local_type -> type ;
6844+ targ_id = targ_type -> type ;
6845+ goto recur ;
6846+ case BTF_KIND_ARRAY :
6847+ local_id = btf_array (local_type )-> type ;
6848+ targ_id = btf_array (targ_type )-> type ;
6849+ goto recur ;
6850+ case BTF_KIND_FUNC_PROTO : {
6851+ struct btf_param * local_p = btf_params (local_type );
6852+ struct btf_param * targ_p = btf_params (targ_type );
6853+ __u16 local_vlen = btf_vlen (local_type );
6854+ __u16 targ_vlen = btf_vlen (targ_type );
6855+ int i , err ;
6856+
6857+ if (local_vlen != targ_vlen )
6858+ return 0 ;
6859+
6860+ for (i = 0 ; i < local_vlen ; i ++ , local_p ++ , targ_p ++ ) {
6861+ if (level <= 0 )
6862+ return - EINVAL ;
6863+
6864+ btf_type_skip_modifiers (local_btf , local_p -> type , & local_id );
6865+ btf_type_skip_modifiers (targ_btf , targ_p -> type , & targ_id );
6866+ err = __bpf_core_types_are_compat (local_btf , local_id ,
6867+ targ_btf , targ_id ,
6868+ level - 1 );
6869+ if (err <= 0 )
6870+ return err ;
6871+ }
6872+
6873+ /* tail recurse for return type check */
6874+ btf_type_skip_modifiers (local_btf , local_type -> type , & local_id );
6875+ btf_type_skip_modifiers (targ_btf , targ_type -> type , & targ_id );
6876+ goto recur ;
6877+ }
6878+ default :
6879+ return 0 ;
6880+ }
6881+ }
6882+
6883+ /* Check local and target types for compatibility. This check is used for
6884+ * type-based CO-RE relocations and follow slightly different rules than
6885+ * field-based relocations. This function assumes that root types were already
6886+ * checked for name match. Beyond that initial root-level name check, names
6887+ * are completely ignored. Compatibility rules are as follows:
6888+ * - any two STRUCTs/UNIONs/FWDs/ENUMs/INTs are considered compatible, but
6889+ * kind should match for local and target types (i.e., STRUCT is not
6890+ * compatible with UNION);
6891+ * - for ENUMs, the size is ignored;
6892+ * - for INT, size and signedness are ignored;
6893+ * - for ARRAY, dimensionality is ignored, element types are checked for
6894+ * compatibility recursively;
6895+ * - CONST/VOLATILE/RESTRICT modifiers are ignored;
6896+ * - TYPEDEFs/PTRs are compatible if types they pointing to are compatible;
6897+ * - FUNC_PROTOs are compatible if they have compatible signature: same
6898+ * number of input args and compatible return and argument types.
6899+ * These rules are not set in stone and probably will be adjusted as we get
6900+ * more experience with using BPF CO-RE relocations.
6901+ */
68016902int bpf_core_types_are_compat (const struct btf * local_btf , __u32 local_id ,
68026903 const struct btf * targ_btf , __u32 targ_id )
68036904{
6804- return - EOPNOTSUPP ;
6905+ return __bpf_core_types_are_compat (local_btf , local_id ,
6906+ targ_btf , targ_id ,
6907+ MAX_TYPES_ARE_COMPAT_DEPTH );
68056908}
68066909
68076910static bool bpf_core_is_flavor_sep (const char * s )
0 commit comments