Introduce the bpf_map_verified_data_size() helper to get the verified data size from a signed map value, as parsed by the kernel with bpf_map_verify_value_sig(). The same information might be provided by user space tools as well without any helper, for example by adding a second unsigned integer after the verified data+sig size field. However, this alternative seems to increase the code complexity: the kernel has to parse two unsigned integers and check their consistency; user space tools have to parse the module-style appended signature to get the verified data size. Alternatively, each eBPF program could parse the module-style signature by itself, but this would cause duplication of the code. Adding a new helper seems the best choice, it only needs to call the existing function bpf_map_verify_value_sig() and pass the result to the caller. Signed-off-by: Roberto Sassu <roberto.sassu@xxxxxxxxxx> --- include/uapi/linux/bpf.h | 8 ++++++++ kernel/bpf/helpers.c | 15 +++++++++++++++ tools/include/uapi/linux/bpf.h | 8 ++++++++ 3 files changed, 31 insertions(+) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index a8e7803d2593..4a05caa49419 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -5252,6 +5252,13 @@ union bpf_attr { * Pointer to the underlying dynptr data, NULL if the dynptr is * read-only, if the dynptr is invalid, or if the offset and length * is out of bounds. + * + * long bpf_map_verified_data_size(const void *value, u32 value_size) + * Description + * Parse signed map value in *value* with size *value_size*. + * Return + * The size of verified data on success, or a negative error in + * case of failure. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -5458,6 +5465,7 @@ union bpf_attr { FN(dynptr_read), \ FN(dynptr_write), \ FN(dynptr_data), \ + FN(bpf_map_verified_data_size), \ /* */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index 225806a02efb..78c29c4e5d3f 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -1575,6 +1575,19 @@ const struct bpf_func_proto bpf_dynptr_data_proto = { .arg3_type = ARG_CONST_ALLOC_SIZE_OR_ZERO, }; +BPF_CALL_2(bpf_map_verified_data_size, const void *, value, u32, value_size) +{ + return bpf_map_verify_value_sig(value, value_size, false); +} + +const struct bpf_func_proto bpf_map_verified_data_size_proto = { + .func = bpf_map_verified_data_size, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_CONST_SIZE_OR_ZERO, +}; + const struct bpf_func_proto bpf_get_current_task_proto __weak; const struct bpf_func_proto bpf_get_current_task_btf_proto __weak; const struct bpf_func_proto bpf_probe_read_user_proto __weak; @@ -1643,6 +1656,8 @@ bpf_base_func_proto(enum bpf_func_id func_id) return &bpf_dynptr_write_proto; case BPF_FUNC_dynptr_data: return &bpf_dynptr_data_proto; + case BPF_FUNC_bpf_map_verified_data_size: + return &bpf_map_verified_data_size_proto; default: break; } diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index a8e7803d2593..4a05caa49419 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -5252,6 +5252,13 @@ union bpf_attr { * Pointer to the underlying dynptr data, NULL if the dynptr is * read-only, if the dynptr is invalid, or if the offset and length * is out of bounds. + * + * long bpf_map_verified_data_size(const void *value, u32 value_size) + * Description + * Parse signed map value in *value* with size *value_size*. + * Return + * The size of verified data on success, or a negative error in + * case of failure. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -5458,6 +5465,7 @@ union bpf_attr { FN(dynptr_read), \ FN(dynptr_write), \ FN(dynptr_data), \ + FN(bpf_map_verified_data_size), \ /* */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper -- 2.25.1