Message ID | 20210216011216.3168-5-iii@linux.ibm.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | BPF |
Headers | show |
Series | Add BTF_KIND_FLOAT support | expand |
Context | Check | Description |
---|---|---|
netdev/cover_letter | success | Link |
netdev/fixes_present | success | Link |
netdev/patch_count | success | Link |
netdev/tree_selection | success | Clearly marked for bpf-next |
netdev/subject_prefix | success | Link |
netdev/cc_maintainers | warning | 5 maintainers not CCed: netdev@vger.kernel.org john.fastabend@gmail.com kpsingh@kernel.org songliubraving@fb.com kafai@fb.com |
netdev/source_inline | success | Was 0 now: 0 |
netdev/verify_signedoff | success | Link |
netdev/module_param | success | Was 0 now: 0 |
netdev/build_32bit | success | Errors and warnings before: 9 this patch: 9 |
netdev/kdoc | success | Errors and warnings before: 0 this patch: 0 |
netdev/verify_fixes | success | Link |
netdev/checkpatch | success | total: 0 errors, 0 warnings, 0 checks, 108 lines checked |
netdev/build_allmodconfig_warn | success | Errors and warnings before: 9 this patch: 9 |
netdev/header_inline | success | Link |
netdev/stable | success | Stable not CCed |
On 2/15/21 5:12 PM, Ilya Leoshkevich wrote: > 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. > > Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> > --- > kernel/bpf/btf.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 64 insertions(+), 2 deletions(-) > > diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c > index 2efeb5f4b343..6c73e5484409 100644 > --- a/kernel/bpf/btf.c > +++ b/kernel/bpf/btf.c > @@ -173,7 +173,7 @@ > #define BITS_ROUNDUP_BYTES(bits) \ > (BITS_ROUNDDOWN_BYTES(bits) + !!BITS_PER_BYTE_MASKED(bits)) > > -#define BTF_INFO_MASK 0x8f00ffff > +#define BTF_INFO_MASK 0x9f00ffff > #define BTF_INT_MASK 0x0fffffff > #define BTF_TYPE_ID_VALID(type_id) ((type_id) <= BTF_MAX_TYPE) > #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] = { > [BTF_KIND_FUNC_PROTO] = "FUNC_PROTO", > [BTF_KIND_VAR] = "VAR", > [BTF_KIND_DATASEC] = "DATASEC", > + [BTF_KIND_FLOAT] = "FLOAT", > }; > > 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) > case BTF_KIND_UNION: > case BTF_KIND_ENUM: > case BTF_KIND_DATASEC: > + case BTF_KIND_FLOAT: > return true; > } > > @@ -1704,6 +1706,7 @@ __btf_resolve_size(const struct btf *btf, const struct btf_type *type, > case BTF_KIND_STRUCT: > case BTF_KIND_UNION: > case BTF_KIND_ENUM: > + case BTF_KIND_FLOAT: > size = type->size; > goto resolved; > > @@ -1849,7 +1852,7 @@ static int btf_df_check_kflag_member(struct btf_verifier_env *env, > return -EINVAL; > } > > -/* Used for ptr, array and struct/union type members. > +/* Used for ptr, array struct/union and float type members. > * int, enum and modifier types have their specific callback functions. > */ > static int btf_generic_check_kflag_member(struct btf_verifier_env *env, > @@ -3675,6 +3678,64 @@ static const struct btf_kind_operations datasec_ops = { > .show = btf_datasec_show, > }; > > +static s32 btf_float_check_meta(struct btf_verifier_env *env, > + const struct btf_type *t, > + u32 meta_left) > +{ > + if (btf_type_vlen(t)) { > + btf_verifier_log_type(env, t, "vlen != 0"); > + return -EINVAL; > + } > + > + if (btf_type_kflag(t)) { > + btf_verifier_log_type(env, t, "Invalid btf_info kind_flag"); > + return -EINVAL; > + } I think we should enforce proper float size as well (2/4/8/16). > + > + btf_verifier_log_type(env, t, NULL); > + > + return 0; > +} > + > +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) > +{ > + u64 end_offset_bytes; > + u64 end_offset_bits; > + u64 offset_bits; > + u64 size_bits; > + > + size_bits = member_type->size * BITS_PER_BYTE; > + offset_bits = member->offset; float type cannot be used for bitfield, so offset here must of a multiple of allowed alignment, i.e., min(ptr_size, member_type->size). We should enforce here. > + end_offset_bits = offset_bits + size_bits; > + end_offset_bytes = BITS_ROUNDUP_BYTES(end_offset_bits); There is no need to do BITS_ROUNDUP_BYTES if we enforce member->offset as in the above. > + > + if (end_offset_bytes > struct_type->size) { > + btf_verifier_log_member(env, struct_type, member, > + "Member exceeds struct_size"); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static void btf_float_log(struct btf_verifier_env *env, > + const struct btf_type *t) > +{ > + btf_verifier_log(env, "size=%u", t->size); > +} > + > +static const struct btf_kind_operations float_ops = { > + .check_meta = btf_float_check_meta, > + .resolve = btf_df_resolve, > + .check_member = btf_float_check_member, > + .check_kflag_member = btf_generic_check_kflag_member, > + .log_details = btf_float_log, > + .show = btf_df_show, > +}; > + > static int btf_func_proto_check(struct btf_verifier_env *env, > const struct btf_type *t) > { > @@ -3808,6 +3869,7 @@ static const struct btf_kind_operations * const kind_ops[NR_BTF_KINDS] = { > [BTF_KIND_FUNC_PROTO] = &func_proto_ops, > [BTF_KIND_VAR] = &var_ops, > [BTF_KIND_DATASEC] = &datasec_ops, > + [BTF_KIND_FLOAT] = &float_ops, > }; > > static s32 btf_check_meta(struct btf_verifier_env *env, >
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 2efeb5f4b343..6c73e5484409 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -173,7 +173,7 @@ #define BITS_ROUNDUP_BYTES(bits) \ (BITS_ROUNDDOWN_BYTES(bits) + !!BITS_PER_BYTE_MASKED(bits)) -#define BTF_INFO_MASK 0x8f00ffff +#define BTF_INFO_MASK 0x9f00ffff #define BTF_INT_MASK 0x0fffffff #define BTF_TYPE_ID_VALID(type_id) ((type_id) <= BTF_MAX_TYPE) #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] = { [BTF_KIND_FUNC_PROTO] = "FUNC_PROTO", [BTF_KIND_VAR] = "VAR", [BTF_KIND_DATASEC] = "DATASEC", + [BTF_KIND_FLOAT] = "FLOAT", }; 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) case BTF_KIND_UNION: case BTF_KIND_ENUM: case BTF_KIND_DATASEC: + case BTF_KIND_FLOAT: return true; } @@ -1704,6 +1706,7 @@ __btf_resolve_size(const struct btf *btf, const struct btf_type *type, case BTF_KIND_STRUCT: case BTF_KIND_UNION: case BTF_KIND_ENUM: + case BTF_KIND_FLOAT: size = type->size; goto resolved; @@ -1849,7 +1852,7 @@ static int btf_df_check_kflag_member(struct btf_verifier_env *env, return -EINVAL; } -/* Used for ptr, array and struct/union type members. +/* Used for ptr, array struct/union and float type members. * int, enum and modifier types have their specific callback functions. */ static int btf_generic_check_kflag_member(struct btf_verifier_env *env, @@ -3675,6 +3678,64 @@ static const struct btf_kind_operations datasec_ops = { .show = btf_datasec_show, }; +static s32 btf_float_check_meta(struct btf_verifier_env *env, + const struct btf_type *t, + u32 meta_left) +{ + if (btf_type_vlen(t)) { + btf_verifier_log_type(env, t, "vlen != 0"); + return -EINVAL; + } + + if (btf_type_kflag(t)) { + btf_verifier_log_type(env, t, "Invalid btf_info kind_flag"); + return -EINVAL; + } + + btf_verifier_log_type(env, t, NULL); + + return 0; +} + +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) +{ + u64 end_offset_bytes; + u64 end_offset_bits; + u64 offset_bits; + u64 size_bits; + + size_bits = member_type->size * BITS_PER_BYTE; + offset_bits = member->offset; + end_offset_bits = offset_bits + size_bits; + end_offset_bytes = BITS_ROUNDUP_BYTES(end_offset_bits); + + if (end_offset_bytes > struct_type->size) { + btf_verifier_log_member(env, struct_type, member, + "Member exceeds struct_size"); + return -EINVAL; + } + + return 0; +} + +static void btf_float_log(struct btf_verifier_env *env, + const struct btf_type *t) +{ + btf_verifier_log(env, "size=%u", t->size); +} + +static const struct btf_kind_operations float_ops = { + .check_meta = btf_float_check_meta, + .resolve = btf_df_resolve, + .check_member = btf_float_check_member, + .check_kflag_member = btf_generic_check_kflag_member, + .log_details = btf_float_log, + .show = btf_df_show, +}; + static int btf_func_proto_check(struct btf_verifier_env *env, const struct btf_type *t) { @@ -3808,6 +3869,7 @@ static const struct btf_kind_operations * const kind_ops[NR_BTF_KINDS] = { [BTF_KIND_FUNC_PROTO] = &func_proto_ops, [BTF_KIND_VAR] = &var_ops, [BTF_KIND_DATASEC] = &datasec_ops, + [BTF_KIND_FLOAT] = &float_ops, }; static s32 btf_check_meta(struct btf_verifier_env *env,
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. Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> --- kernel/bpf/btf.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-)