On the kernel side, introduce a new btf_kind_operations. It is similar to that of BTF_KIND_INT, however, it does not need to handle encodings and bit offsets. Do not implement printing, since the kernel does not know how to format floating-point values.
Unified · Split
| @@ -173,7 +173,7 @@ · 172 unmodified lines | ||
| 173 | 173 | #define BITS_ROUNDUP_BYTES(bits) \ |
| 174 | 174 | (BITS_ROUNDDOWN_BYTES(bits) + !!BITS_PER_BYTE_MASKED(bits)) |
| 175 | 175 | |
| 176 | −#define BTF_INFO_MASK 0x8f00ffff | |
| 176 | +#define BTF_INFO_MASK 0x9f00ffff | |
| 177 | 177 | #define BTF_INT_MASK 0x0fffffff |
| 178 | 178 | #define BTF_TYPE_ID_VALID(type_id) ((type_id) <= BTF_MAX_TYPE) |
| 179 | 179 | #define BTF_STR_OFFSET_VALID(name_off) ((name_off) <= BTF_MAX_NAME_OFFSET) |
| @@ -280,6 +280,7 @@ static const char * const btf_kind_str[NR_BTF_KINDS] = { · 100 unmodified lines | ||
| 280 | 280 | [BTF_KIND_FUNC_PROTO] = "FUNC_PROTO", |
| 281 | 281 | [BTF_KIND_VAR] = "VAR", |
| 282 | 282 | [BTF_KIND_DATASEC] = "DATASEC", |
| 283 | + [BTF_KIND_FLOAT] = "FLOAT", | |
| 283 | 284 | }; |
| 284 | 285 | |
| 285 | 286 | static const char *btf_type_str(const struct btf_type *t) |
| @@ -574,6 +575,7 @@ static bool btf_type_has_size(const struct btf_type *t) · 288 unmodified lines | ||
| 574 | 575 | case BTF_KIND_UNION: |
| 575 | 576 | case BTF_KIND_ENUM: |
| 576 | 577 | case BTF_KIND_DATASEC: |
| 578 | + case BTF_KIND_FLOAT: | |
| 577 | 579 | return true; |
| 578 | 580 | } |
| 579 | 581 | |
| @@ -1704,6 +1706,7 @@ __btf_resolve_size(const struct btf *btf, const struct btf_type *type, · 1124 unmodified lines | ||
| 1704 | 1706 | case BTF_KIND_STRUCT: |
| 1705 | 1707 | case BTF_KIND_UNION: |
| 1706 | 1708 | case BTF_KIND_ENUM: |
| 1709 | + case BTF_KIND_FLOAT: | |
| 1707 | 1710 | size = type->size; |
| 1708 | 1711 | goto resolved; |
| 1709 | 1712 | |
| @@ -1849,7 +1852,7 @@ static int btf_df_check_kflag_member(struct btf_verifier_env *env, · 139 unmodified lines | ||
| 1849 | 1852 | return -EINVAL; |
| 1850 | 1853 | } |
| 1851 | 1854 | |
| 1852 | −/* Used for ptr, array and struct/union type members. | |
| 1855 | +/* Used for ptr, array struct/union and float type members. | |
| 1853 | 1856 | * int, enum and modifier types have their specific callback functions. |
| 1854 | 1857 | */ |
| 1855 | 1858 | static int btf_generic_check_kflag_member(struct btf_verifier_env *env, |
| @@ -3675,6 +3678,81 @@ static const struct btf_kind_operations datasec_ops = { · 1819 unmodified lines | ||
| 3675 | 3678 | .show = btf_datasec_show, |
| 3676 | 3679 | }; |
| 3677 | 3680 | |
| 3681 | +static s32 btf_float_check_meta(struct btf_verifier_env *env, | |
| 3682 | + const struct btf_type *t, | |
| 3683 | + u32 meta_left) | |
| 3684 | +{ | |
| 3685 | + if (btf_type_vlen(t)) { | |
| 3686 | + btf_verifier_log_type(env, t, "vlen != 0"); | |
| 3687 | + return -EINVAL; | |
| 3688 | + } | |
| 3689 | + | |
| 3690 | + if (btf_type_kflag(t)) { | |
| 3691 | + btf_verifier_log_type(env, t, "Invalid btf_info kind_flag"); | |
| 3692 | + return -EINVAL; | |
| 3693 | + } | |
| 3694 | + | |
| 3695 | + if (t->size != 2 && t->size != 4 && t->size != 8 && t->size != 12 && | |
| 3696 | + t->size != 16) { | |
| 3697 | + btf_verifier_log_type(env, t, "Invalid type_size"); | |
| 3698 | + return -EINVAL; | |
| 3699 | + } | |
| 3700 | + | |
| 3701 | + btf_verifier_log_type(env, t, NULL); | |
| 3702 | + | |
| 3703 | + return 0; | |
| 3704 | +} | |
| 3705 | + | |
| 3706 | +static int btf_float_check_member(struct btf_verifier_env *env, | |
| 3707 | + const struct btf_type *struct_type, | |
| 3708 | + const struct btf_member *member, | |
| 3709 | + const struct btf_type *member_type) | |
| 3710 | +{ | |
| 3711 | + u64 start_offset_bytes; | |
| 3712 | + u64 end_offset_bytes; | |
| 3713 | + u64 misalign_bits; | |
| 3714 | + u64 align_bytes; | |
| 3715 | + u64 align_bits; | |
| 3716 | + | |
| 3717 | + /* Different architectures have different alignment requirements, so | |
| 3718 | + * here we check only for the reasonable minimum. This way we ensure | |
| 3719 | + * that types after CO-RE can pass the kernel BTF verifier. | |
| 3720 | + */ | |
| 3721 | + align_bytes = min_t(u64, sizeof(void *), member_type->size); | |
| 3722 | + align_bits = align_bytes * BITS_PER_BYTE; | |
| 3723 | + div64_u64_rem(member->offset, align_bits, &misalign_bits); | |
| 3724 | + if (misalign_bits) { | |
| 3725 | + btf_verifier_log_member(env, struct_type, member, | |
| 3726 | + "Member is not properly aligned"); | |
| 3727 | + return -EINVAL; | |
| 3728 | + } | |
| 3729 | + | |
| 3730 | + start_offset_bytes = member->offset / BITS_PER_BYTE; | |
| 3731 | + end_offset_bytes = start_offset_bytes + member_type->size; | |
| 3732 | + if (end_offset_bytes > struct_type->size) { | |
| 3733 | + btf_verifier_log_member(env, struct_type, member, | |
| 3734 | + "Member exceeds struct_size"); | |
| 3735 | + return -EINVAL; | |
| 3736 | + } | |
| 3737 | + | |
| 3738 | + return 0; | |
| 3739 | +} | |
| 3740 | + | |
| 3741 | +static void btf_float_log(struct btf_verifier_env *env, | |
| 3742 | + const struct btf_type *t) | |
| 3743 | +{ | |
| 3744 | + btf_verifier_log(env, "size=%u", t->size); | |
| 3745 | +} | |
| 3746 | + | |
| 3747 | +static const struct btf_kind_operations float_ops = { | |
| 3748 | + .check_meta = btf_float_check_meta, | |
| 3749 | + .resolve = btf_df_resolve, | |
| 3750 | + .check_member = btf_float_check_member, | |
| 3751 | + .check_kflag_member = btf_generic_check_kflag_member, | |
| 3752 | + .log_details = btf_float_log, | |
| 3753 | + .show = btf_df_show, | |
| 3754 | +}; | |
| 3755 | + | |
| 3678 | 3756 | static int btf_func_proto_check(struct btf_verifier_env *env, |
| 3679 | 3757 | const struct btf_type *t) |
| 3680 | 3758 | { |
| @@ -3808,6 +3886,7 @@ static const struct btf_kind_operations * const kind_ops[NR_BTF_KINDS] = { · 127 unmodified lines | ||
| 3808 | 3886 | [BTF_KIND_FUNC_PROTO] = &func_proto_ops, |
| 3809 | 3887 | [BTF_KIND_VAR] = &var_ops, |
| 3810 | 3888 | [BTF_KIND_DATASEC] = &datasec_ops, |
| 3889 | + [BTF_KIND_FLOAT] = &float_ops, | |
| 3811 | 3890 | }; |
| 3812 | 3891 | |
| 3813 | 3892 | static s32 btf_check_meta(struct btf_verifier_env *env, |