diff mbox series

[2/3] bpf: Introduce bpf_map_verified_data_size() helper

Message ID 20220525132115.896698-3-roberto.sassu@huawei.com
State New
Headers show
Series bpf: Add support for maps with authenticated values | expand

Commit Message

Roberto Sassu May 25, 2022, 1:21 p.m. UTC
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@huawei.com>
---
 include/uapi/linux/bpf.h       |  8 ++++++++
 kernel/bpf/helpers.c           | 15 +++++++++++++++
 tools/include/uapi/linux/bpf.h |  8 ++++++++
 3 files changed, 31 insertions(+)
diff mbox series

Patch

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