All of lore.kernel.org
 help / color / mirror / Atom feed
From: Joanne Koong <joannelkoong@gmail.com>
To: bpf@vger.kernel.org
Cc: andrii@kernel.org, kernel-team@meta.com, ast@kernel.org,
	daniel@iogearbox.net, martin.lau@linux.dev, song@kernel.org,
	Joanne Koong <joannelkoong@gmail.com>
Subject: [PATCH v2 bpf-next 1/6] bpf: Add bpf_dynptr_trim and bpf_dynptr_advance
Date: Wed,  7 Dec 2022 12:55:32 -0800	[thread overview]
Message-ID: <20221207205537.860248-2-joannelkoong@gmail.com> (raw)
In-Reply-To: <20221207205537.860248-1-joannelkoong@gmail.com>

Add two new helper functions: bpf_dynptr_trim and bpf_dynptr_advance.

bpf_dynptr_trim decreases the size of a dynptr by the specified
number of bytes (offset remains the same). bpf_dynptr_advance advances
the offset of the dynptr by the specified number of bytes (size
decreases correspondingly).

One example where trimming / advancing the dynptr may useful is for
hashing. If the dynptr points to a larger struct, it is possible to hash
an individual field within the struct through dynptrs by using
bpf_dynptr_advance+trim.

Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
---
 include/uapi/linux/bpf.h       | 18 +++++++++
 kernel/bpf/helpers.c           | 67 ++++++++++++++++++++++++++++++++++
 tools/include/uapi/linux/bpf.h | 18 +++++++++
 3 files changed, 103 insertions(+)

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index a9bb98365031..c2d915601484 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -5537,6 +5537,22 @@ union bpf_attr {
  *		*flags* is currently unused, it must be 0 for now.
  *	Return
  *		0 on success, -EINVAL if flags is not 0.
+ *
+ * long bpf_dynptr_advance(struct bpf_dynptr *ptr, u32 len)
+ *	Description
+ *		Advance a dynptr's internal offset by *len* bytes.
+ *	Return
+ *		0 on success, -EINVAL if the dynptr is invalid, -ERANGE if *len*
+ *		exceeds the bounds of the dynptr.
+ *
+ * long bpf_dynptr_trim(struct bpf_dynptr *ptr, u32 len)
+ *	Description
+ *		Trim the size of memory pointed to by the dynptr by *len* bytes.
+ *
+ *		The offset is unmodified.
+ *	Return
+ *		0 on success, -EINVAL if the dynptr is invalid, -ERANGE if
+ *		trying to trim more bytes than the size of the dynptr.
  */
 #define ___BPF_FUNC_MAPPER(FN, ctx...)			\
 	FN(unspec, 0, ##ctx)				\
@@ -5753,6 +5769,8 @@ union bpf_attr {
 	FN(cgrp_storage_delete, 211, ##ctx)		\
 	FN(dynptr_from_skb, 212, ##ctx)			\
 	FN(dynptr_from_xdp, 213, ##ctx)			\
+	FN(dynptr_advance, 214, ##ctx)			\
+	FN(dynptr_trim, 215, ##ctx)			\
 	/* */
 
 /* backwards-compatibility macros for users of __BPF_FUNC_MAPPER that don't
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 3a9c8814aaf6..fa3989047ff6 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -1429,6 +1429,13 @@ u32 bpf_dynptr_get_size(struct bpf_dynptr_kern *ptr)
 	return ptr->size & DYNPTR_SIZE_MASK;
 }
 
+static void bpf_dynptr_set_size(struct bpf_dynptr_kern *ptr, u32 new_size)
+{
+	u32 metadata = ptr->size & ~DYNPTR_SIZE_MASK;
+
+	ptr->size = new_size | metadata;
+}
+
 int bpf_dynptr_check_size(u32 size)
 {
 	return size > DYNPTR_MAX_SIZE ? -E2BIG : 0;
@@ -1640,6 +1647,62 @@ static const struct bpf_func_proto bpf_dynptr_data_proto = {
 	.arg3_type	= ARG_CONST_ALLOC_SIZE_OR_ZERO,
 };
 
+/* For dynptrs, the offset may only be advanced and the size may only be decremented */
+static int bpf_dynptr_adjust(struct bpf_dynptr_kern *ptr, u32 off_inc, u32 sz_dec)
+{
+	u32 size;
+
+	if (!ptr->data)
+		return -EINVAL;
+
+	size = bpf_dynptr_get_size(ptr);
+
+	if (sz_dec > size)
+		return -ERANGE;
+
+	if (off_inc) {
+		u32 new_off;
+
+		if (off_inc > size)
+			return -ERANGE;
+
+		if (check_add_overflow(ptr->offset, off_inc, &new_off))
+			return -ERANGE;
+
+		ptr->offset = new_off;
+	}
+
+	bpf_dynptr_set_size(ptr, size - sz_dec);
+
+	return 0;
+}
+
+BPF_CALL_2(bpf_dynptr_advance, struct bpf_dynptr_kern *, ptr, u32, len)
+{
+	return bpf_dynptr_adjust(ptr, len, len);
+}
+
+static const struct bpf_func_proto bpf_dynptr_advance_proto = {
+	.func		= bpf_dynptr_advance,
+	.gpl_only	= false,
+	.ret_type	= RET_INTEGER,
+	.arg1_type	= ARG_PTR_TO_DYNPTR,
+	.arg2_type	= ARG_ANYTHING,
+};
+
+BPF_CALL_2(bpf_dynptr_trim, struct bpf_dynptr_kern *, ptr, u32, len)
+{
+	return bpf_dynptr_adjust(ptr, 0, len);
+}
+
+static const struct bpf_func_proto bpf_dynptr_trim_proto = {
+	.func		= bpf_dynptr_trim,
+	.gpl_only	= false,
+	.ret_type	= RET_INTEGER,
+	.arg1_type	= ARG_PTR_TO_DYNPTR,
+	.arg2_type	= ARG_ANYTHING,
+};
+
 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;
@@ -1744,6 +1807,10 @@ 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_dynptr_advance:
+		return &bpf_dynptr_advance_proto;
+	case BPF_FUNC_dynptr_trim:
+		return &bpf_dynptr_trim_proto;
 #ifdef CONFIG_CGROUPS
 	case BPF_FUNC_cgrp_storage_get:
 		return &bpf_cgrp_storage_get_proto;
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index a9bb98365031..c2d915601484 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -5537,6 +5537,22 @@ union bpf_attr {
  *		*flags* is currently unused, it must be 0 for now.
  *	Return
  *		0 on success, -EINVAL if flags is not 0.
+ *
+ * long bpf_dynptr_advance(struct bpf_dynptr *ptr, u32 len)
+ *	Description
+ *		Advance a dynptr's internal offset by *len* bytes.
+ *	Return
+ *		0 on success, -EINVAL if the dynptr is invalid, -ERANGE if *len*
+ *		exceeds the bounds of the dynptr.
+ *
+ * long bpf_dynptr_trim(struct bpf_dynptr *ptr, u32 len)
+ *	Description
+ *		Trim the size of memory pointed to by the dynptr by *len* bytes.
+ *
+ *		The offset is unmodified.
+ *	Return
+ *		0 on success, -EINVAL if the dynptr is invalid, -ERANGE if
+ *		trying to trim more bytes than the size of the dynptr.
  */
 #define ___BPF_FUNC_MAPPER(FN, ctx...)			\
 	FN(unspec, 0, ##ctx)				\
@@ -5753,6 +5769,8 @@ union bpf_attr {
 	FN(cgrp_storage_delete, 211, ##ctx)		\
 	FN(dynptr_from_skb, 212, ##ctx)			\
 	FN(dynptr_from_xdp, 213, ##ctx)			\
+	FN(dynptr_advance, 214, ##ctx)			\
+	FN(dynptr_trim, 215, ##ctx)			\
 	/* */
 
 /* backwards-compatibility macros for users of __BPF_FUNC_MAPPER that don't
-- 
2.30.2


  reply	other threads:[~2022-12-07 21:19 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-07 20:55 [PATCH v2 bpf-next 0/6] Dynptr convenience helpers Joanne Koong
2022-12-07 20:55 ` Joanne Koong [this message]
2022-12-07 20:55 ` [PATCH v2 bpf-next 2/6] bpf: Add bpf_dynptr_is_null and bpf_dynptr_is_rdonly Joanne Koong
2022-12-07 20:55 ` [PATCH v2 bpf-next 3/6] bpf: Add bpf_dynptr_get_size and bpf_dynptr_get_offset Joanne Koong
2022-12-07 20:55 ` [PATCH v2 bpf-next 4/6] bpf: Add bpf_dynptr_clone Joanne Koong
2022-12-07 20:55 ` [PATCH v2 bpf-next 5/6] bpf: Add bpf_dynptr_iterator Joanne Koong
2022-12-07 20:55 ` [PATCH v2 bpf-next 6/6] selftests/bpf: Tests for dynptr convenience helpers Joanne Koong
2022-12-08  1:54 ` [PATCH v2 bpf-next 0/6] Dynptr " Alexei Starovoitov
2022-12-09  0:42   ` Andrii Nakryiko
2022-12-09  1:30     ` Alexei Starovoitov
2022-12-09 22:24       ` Joanne Koong
2022-12-12 20:12       ` Andrii Nakryiko
2022-12-13 23:50         ` Joanne Koong
2022-12-14  0:57           ` Andrii Nakryiko
2022-12-14 21:25             ` Joanne Koong
2022-12-16 17:35         ` Alexei Starovoitov
2022-12-20 19:31           ` Andrii Nakryiko
2022-12-25 21:52             ` bpf helpers freeze. Was: " Alexei Starovoitov
2022-12-29 23:10               ` Andrii Nakryiko
2022-12-30  2:46                 ` Alexei Starovoitov
2022-12-30 18:38                   ` David Vernet
2022-12-30 19:31                     ` Alexei Starovoitov
2022-12-30 21:00                       ` David Vernet
2022-12-31  0:42                         ` Alexei Starovoitov
2023-01-03 11:43                           ` Daniel Borkmann
2023-01-03 23:51                             ` Alexei Starovoitov
2023-01-04 14:25                               ` Daniel Borkmann
2023-01-04 18:59                                 ` Andrii Nakryiko
2023-01-04 20:03                                   ` Alexei Starovoitov
2023-01-04 21:57                                     ` Andrii Nakryiko
2023-01-04 19:37                                 ` Alexei Starovoitov
2023-01-05  0:13                                   ` Martin KaFai Lau
2023-01-05 17:17                                     ` KP Singh
2023-01-05 21:03                                       ` Andrii Nakryiko
2023-01-06  1:32                                         ` KP Singh
2023-01-05 21:02                                     ` Andrii Nakryiko
2023-01-04 20:50                                 ` David Vernet
2023-01-11 22:56                               ` Maxim Mikityanskiy
2023-01-12  4:48                                 ` Alexei Starovoitov
2023-01-13  9:48                                   ` Jose E. Marchesi
2023-01-13 16:35                                     ` Alexei Starovoitov
2023-01-04  0:55                           ` Jakub Kicinski
2023-01-04 18:44                           ` Andrii Nakryiko
2023-01-04 19:56                             ` Alexei Starovoitov
2023-01-04 18:43                         ` Andrii Nakryiko
2023-01-04 19:51                           ` Alexei Starovoitov
2023-01-04 21:56                             ` Andrii Nakryiko
2023-01-04 18:43                   ` Andrii Nakryiko
2023-01-04 19:44                     ` Alexei Starovoitov
2023-01-04 21:55                       ` Andrii Nakryiko
2023-01-04 23:47                         ` David Vernet
2023-01-05 21:01                           ` Andrii Nakryiko
2023-01-06  2:54                             ` Alexei Starovoitov
2023-01-09 17:46                               ` Andrii Nakryiko
2023-01-11 21:29                                 ` Song Liu
2023-01-12  4:23                                   ` Alexei Starovoitov
2023-01-12  7:35                                     ` Song Liu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221207205537.860248-2-joannelkoong@gmail.com \
    --to=joannelkoong@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=kernel-team@meta.com \
    --cc=martin.lau@linux.dev \
    --cc=song@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.