| @@ -281,6 +281,7 @@ static const char * const btf_kind_str[NR_BTF_KINDS] = { · 280 unmodified lines |
| 281 | [BTF_KIND_VAR] = "VAR", | 281 | [BTF_KIND_VAR] = "VAR", |
| 282 | [BTF_KIND_DATASEC] = "DATASEC", | 282 | [BTF_KIND_DATASEC] = "DATASEC", |
| 283 | [BTF_KIND_FLOAT] = "FLOAT", | 283 | [BTF_KIND_FLOAT] = "FLOAT", |
| | 284 | [BTF_KIND_TAG] = "TAG", |
| 284 | }; | 285 | }; |
| 285 | | 286 | |
| 286 | const char *btf_type_str(const struct btf_type *t) | 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 | return BTF_INFO_KIND(t->info) == BTF_KIND_DATASEC; | 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 | u32 btf_nr_types(const struct btf *btf) | 474 | u32 btf_nr_types(const struct btf *btf) |
| 463 | { | 475 | { |
| 464 | u32 total = 0; | 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 | static bool btf_type_is_resolve_source_only(const struct btf_type *t) | 549 | static bool btf_type_is_resolve_source_only(const struct btf_type *t) |
| 538 | { | 550 | { |
| 539 | return btf_type_is_var(t) || | 551 | return btf_type_is_var(t) || |
| | 552 | btf_type_is_tag(t) || |
| 540 | btf_type_is_datasec(t); | 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 | btf_type_is_struct(t) || | 576 | btf_type_is_struct(t) || |
| 564 | btf_type_is_array(t) || | 577 | btf_type_is_array(t) || |
| 565 | btf_type_is_var(t) || | 578 | btf_type_is_var(t) || |
| | 579 | btf_type_is_tag(t) || |
| 566 | btf_type_is_datasec(t); | 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 | return (const struct btf_var *)(t + 1); | 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 | static const struct btf_kind_operations *btf_type_ops(const struct btf_type *t) | 638 | static const struct btf_kind_operations *btf_type_ops(const struct btf_type *t) |
| 620 | { | 639 | { |
| 621 | return kind_ops[BTF_INFO_KIND(t->info)]; | 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 | .show = btf_df_show, | 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 | static int btf_func_proto_check(struct btf_verifier_env *env, | 3927 | static int btf_func_proto_check(struct btf_verifier_env *env, |
| 3805 | const struct btf_type *t) | 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 | [BTF_KIND_VAR] = &var_ops, | 4058 | [BTF_KIND_VAR] = &var_ops, |
| 3936 | [BTF_KIND_DATASEC] = &datasec_ops, | 4059 | [BTF_KIND_DATASEC] = &datasec_ops, |
| 3937 | [BTF_KIND_FLOAT] = &float_ops, | 4060 | [BTF_KIND_FLOAT] = &float_ops, |
| | 4061 | [BTF_KIND_TAG] = &tag_ops, |
| 3938 | }; | 4062 | }; |
| 3939 | | 4063 | |
| 3940 | static s32 btf_check_meta(struct btf_verifier_env *env, | 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 | return !btf_resolved_type_id(btf, type_id) && | 4143 | return !btf_resolved_type_id(btf, type_id) && |
| 4020 | !btf_resolved_type_size(btf, type_id); | 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 | if (btf_type_is_modifier(t) || btf_type_is_ptr(t) || | 4150 | if (btf_type_is_modifier(t) || btf_type_is_ptr(t) || |
| 4023 | btf_type_is_var(t)) { | 4151 | btf_type_is_var(t)) { |
| 4024 | t = btf_type_id_resolve(btf, &type_id); | 4152 | t = btf_type_id_resolve(btf, &type_id); |