| @@ -281,6 +281,7 @@ static const char * const btf_kind_str[NR_BTF_KINDS] = { · 280 unmodified lines |
| 281 | 281 | [BTF_KIND_VAR] = "VAR", |
| 282 | 282 | [BTF_KIND_DATASEC] = "DATASEC", |
| 283 | 283 | [BTF_KIND_FLOAT] = "FLOAT", |
| 284 | + [BTF_KIND_TAG] = "TAG", |
| 284 | 285 | }; |
| 285 | 286 | |
| 286 | 287 | const char *btf_type_str(const struct btf_type *t) |
| @@ -459,6 +460,17 @@ static bool btf_type_is_datasec(const struct btf_type *t) · 172 unmodified lines |
| 459 | 460 | return BTF_INFO_KIND(t->info) == BTF_KIND_DATASEC; |
| 460 | 461 | } |
| 461 | 462 | |
| 463 | +static bool btf_type_is_tag(const struct btf_type *t) |
| 464 | +{ |
| 465 | + return BTF_INFO_KIND(t->info) == BTF_KIND_TAG; |
| 466 | +} |
| 467 | + |
| 468 | +static bool btf_type_is_tag_target(const struct btf_type *t) |
| 469 | +{ |
| 470 | + return btf_type_is_func(t) || btf_type_is_struct(t) || |
| 471 | + btf_type_is_var(t); |
| 472 | +} |
| 473 | + |
| 462 | 474 | u32 btf_nr_types(const struct btf *btf) |
| 463 | 475 | { |
| 464 | 476 | u32 total = 0; |
| @@ -537,6 +549,7 @@ const struct btf_type *btf_type_resolve_func_ptr(const struct btf *btf, · 72 unmodified lines |
| 537 | 549 | static bool btf_type_is_resolve_source_only(const struct btf_type *t) |
| 538 | 550 | { |
| 539 | 551 | return btf_type_is_var(t) || |
| 552 | + btf_type_is_tag(t) || |
| 540 | 553 | btf_type_is_datasec(t); |
| 541 | 554 | } |
| 542 | 555 | |
| @@ -563,6 +576,7 @@ static bool btf_type_needs_resolve(const struct btf_type *t) · 20 unmodified lines |
| 563 | 576 | btf_type_is_struct(t) || |
| 564 | 577 | btf_type_is_array(t) || |
| 565 | 578 | btf_type_is_var(t) || |
| 579 | + btf_type_is_tag(t) || |
| 566 | 580 | btf_type_is_datasec(t); |
| 567 | 581 | } |
| 568 | 582 | |
| @@ -616,6 +630,11 @@ static const struct btf_var *btf_type_var(const struct btf_type *t) · 47 unmodified lines |
| 616 | 630 | return (const struct btf_var *)(t + 1); |
| 617 | 631 | } |
| 618 | 632 | |
| 633 | +static const struct btf_tag *btf_type_tag(const struct btf_type *t) |
| 634 | +{ |
| 635 | + return (const struct btf_tag *)(t + 1); |
| 636 | +} |
| 637 | + |
| 619 | 638 | static const struct btf_kind_operations *btf_type_ops(const struct btf_type *t) |
| 620 | 639 | { |
| 621 | 640 | return kind_ops[BTF_INFO_KIND(t->info)]; |
| @@ -3801,6 +3820,110 @@ static const struct btf_kind_operations float_ops = { · 3179 unmodified lines |
| 3801 | 3820 | .show = btf_df_show, |
| 3802 | 3821 | }; |
| 3803 | 3822 | |
| 3823 | +static s32 btf_tag_check_meta(struct btf_verifier_env *env, |
| 3824 | + const struct btf_type *t, |
| 3825 | + u32 meta_left) |
| 3826 | +{ |
| 3827 | + const struct btf_tag *tag; |
| 3828 | + u32 meta_needed = sizeof(*tag); |
| 3829 | + s32 component_idx; |
| 3830 | + const char *value; |
| 3831 | + |
| 3832 | + if (meta_left < meta_needed) { |
| 3833 | + btf_verifier_log_basic(env, t, |
| 3834 | + "meta_left:%u meta_needed:%u", |
| 3835 | + meta_left, meta_needed); |
| 3836 | + return -EINVAL; |
| 3837 | + } |
| 3838 | + |
| 3839 | + value = btf_name_by_offset(env->btf, t->name_off); |
| 3840 | + if (!value || !value[0]) { |
| 3841 | + btf_verifier_log_type(env, t, "Invalid value"); |
| 3842 | + return -EINVAL; |
| 3843 | + } |
| 3844 | + |
| 3845 | + if (btf_type_vlen(t)) { |
| 3846 | + btf_verifier_log_type(env, t, "vlen != 0"); |
| 3847 | + return -EINVAL; |
| 3848 | + } |
| 3849 | + |
| 3850 | + if (btf_type_kflag(t)) { |
| 3851 | + btf_verifier_log_type(env, t, "Invalid btf_info kind_flag"); |
| 3852 | + return -EINVAL; |
| 3853 | + } |
| 3854 | + |
| 3855 | + component_idx = btf_type_tag(t)->component_idx; |
| 3856 | + if (component_idx < -1) { |
| 3857 | + btf_verifier_log_type(env, t, "Invalid component_idx"); |
| 3858 | + return -EINVAL; |
| 3859 | + } |
| 3860 | + |
| 3861 | + btf_verifier_log_type(env, t, NULL); |
| 3862 | + |
| 3863 | + return meta_needed; |
| 3864 | +} |
| 3865 | + |
| 3866 | +static int btf_tag_resolve(struct btf_verifier_env *env, |
| 3867 | + const struct resolve_vertex *v) |
| 3868 | +{ |
| 3869 | + const struct btf_type *next_type; |
| 3870 | + const struct btf_type *t = v->t; |
| 3871 | + u32 next_type_id = t->type; |
| 3872 | + struct btf *btf = env->btf; |
| 3873 | + s32 component_idx; |
| 3874 | + u32 vlen; |
| 3875 | + |
| 3876 | + next_type = btf_type_by_id(btf, next_type_id); |
| 3877 | + if (!next_type || !btf_type_is_tag_target(next_type)) { |
| 3878 | + btf_verifier_log_type(env, v->t, "Invalid type_id"); |
| 3879 | + return -EINVAL; |
| 3880 | + } |
| 3881 | + |
| 3882 | + if (!env_type_is_resolve_sink(env, next_type) && |
| 3883 | + !env_type_is_resolved(env, next_type_id)) |
| 3884 | + return env_stack_push(env, next_type, next_type_id); |
| 3885 | + |
| 3886 | + component_idx = btf_type_tag(t)->component_idx; |
| 3887 | + if (component_idx != -1) { |
| 3888 | + if (btf_type_is_var(next_type)) { |
| 3889 | + btf_verifier_log_type(env, v->t, "Invalid component_idx"); |
| 3890 | + return -EINVAL; |
| 3891 | + } |
| 3892 | + |
| 3893 | + if (btf_type_is_struct(next_type)) { |
| 3894 | + vlen = btf_type_vlen(next_type); |
| 3895 | + } else { |
| 3896 | + /* next_type should be a function */ |
| 3897 | + next_type = btf_type_by_id(btf, next_type->type); |
| 3898 | + vlen = btf_type_vlen(next_type); |
| 3899 | + } |
| 3900 | + |
| 3901 | + if ((u32)component_idx >= vlen) { |
| 3902 | + btf_verifier_log_type(env, v->t, "Invalid component_idx"); |
| 3903 | + return -EINVAL; |
| 3904 | + } |
| 3905 | + } |
| 3906 | + |
| 3907 | + env_stack_pop_resolved(env, next_type_id, 0); |
| 3908 | + |
| 3909 | + return 0; |
| 3910 | +} |
| 3911 | + |
| 3912 | +static void btf_tag_log(struct btf_verifier_env *env, const struct btf_type *t) |
| 3913 | +{ |
| 3914 | + btf_verifier_log(env, "type=%u component_idx=%d", t->type, |
| 3915 | + btf_type_tag(t)->component_idx); |
| 3916 | +} |
| 3917 | + |
| 3918 | +static const struct btf_kind_operations tag_ops = { |
| 3919 | + .check_meta = btf_tag_check_meta, |
| 3920 | + .resolve = btf_tag_resolve, |
| 3921 | + .check_member = btf_df_check_member, |
| 3922 | + .check_kflag_member = btf_df_check_kflag_member, |
| 3923 | + .log_details = btf_tag_log, |
| 3924 | + .show = btf_df_show, |
| 3925 | +}; |
| 3926 | + |
| 3804 | 3927 | static int btf_func_proto_check(struct btf_verifier_env *env, |
| 3805 | 3928 | const struct btf_type *t) |
| 3806 | 3929 | { |
| @@ -3935,6 +4058,7 @@ static const struct btf_kind_operations * const kind_ops[NR_BTF_KINDS] = { · 128 unmodified lines |
| 3935 | 4058 | [BTF_KIND_VAR] = &var_ops, |
| 3936 | 4059 | [BTF_KIND_DATASEC] = &datasec_ops, |
| 3937 | 4060 | [BTF_KIND_FLOAT] = &float_ops, |
| 4061 | + [BTF_KIND_TAG] = &tag_ops, |
| 3938 | 4062 | }; |
| 3939 | 4063 | |
| 3940 | 4064 | static s32 btf_check_meta(struct btf_verifier_env *env, |
| @@ -4019,6 +4143,10 @@ static bool btf_resolve_valid(struct btf_verifier_env *env, · 78 unmodified lines |
| 4019 | 4143 | return !btf_resolved_type_id(btf, type_id) && |
| 4020 | 4144 | !btf_resolved_type_size(btf, type_id); |
| 4021 | 4145 | |
| 4146 | + if (btf_type_is_tag(t)) |
| 4147 | + return btf_resolved_type_id(btf, type_id) && |
| 4148 | + !btf_resolved_type_size(btf, type_id); |
| 4149 | + |
| 4022 | 4150 | if (btf_type_is_modifier(t) || btf_type_is_ptr(t) || |
| 4023 | 4151 | btf_type_is_var(t)) { |
| 4024 | 4152 | t = btf_type_id_resolve(btf, &type_id); |