[PATCH bpf-next v2 05/20] bpf: Introduce an internal map flag BPF_INT_F_DYNPTR_IN_KEY

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Hou Tao <houtao1@xxxxxxxxxx>

Introduce an internal map flag BPF_F_DYNPTR_IN_KEY to support dynptr in
map key. Add the corresponding helper bpf_map_has_dynptr_key() to check
whether the support of dynptr-key is enabled.

The reason for an internal map flag is twofolds:
1) user doesn't need to set the map flag explicitly
map_create() will use the presence of bpf_dynptr in map key as an
indicator of enabling dynptr key.
2) avoid adding new arguments for ->map_alloc_check() and ->map_alloc()
map_create() needs to pass the supported status of dynptr key to
->map_alloc_check (e.g., check the maximum length of dynptr data size)
and ->map_alloc (e.g., check whether dynptr key fits current map type).
Adding new arguments for these callbacks to achieve that will introduce
too much churns.

Therefore, the patch uses the topmost bit of map_flags as the internal
map flag. map_create() checks whether the internal flag is set in the
beginning and bpf_map_get_info_by_fd() clears the internal flag before
returns the map flags to userspace.

Signed-off-by: Hou Tao <houtao1@xxxxxxxxxx>
---
 include/linux/bpf.h  | 17 +++++++++++++++++
 kernel/bpf/syscall.c |  4 +++-
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index ed58d5dd6b34b..ee02a5d313c56 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -258,6 +258,14 @@ struct bpf_list_node_kern {
 	void *owner;
 } __attribute__((aligned(8)));
 
+/* Internal map flags */
+enum {
+	/* map key supports bpf_dynptr */
+	BPF_INT_F_DYNPTR_IN_KEY = (1U << 31),
+};
+
+#define BPF_INT_F_MASK (1U << 31)
+
 struct bpf_map {
 	const struct bpf_map_ops *ops;
 	struct bpf_map *inner_map_meta;
@@ -269,6 +277,10 @@ struct bpf_map {
 	u32 value_size;
 	u32 max_entries;
 	u64 map_extra; /* any per-map-type extra fields */
+	/* The topmost bit of map_flags is used as an internal map flag
+	 * (aka BPF_INT_F_DYNPTR_IN_KEY) and it can't be set through bpf
+	 * syscall.
+	 */
 	u32 map_flags;
 	u32 id;
 	/* BTF record for special fields in map value. bpf_dynptr is disallowed
@@ -317,6 +329,11 @@ struct bpf_map {
 	s64 __percpu *elem_count;
 };
 
+static inline bool bpf_map_has_dynptr_key(const struct bpf_map *map)
+{
+	return map->map_flags & BPF_INT_F_DYNPTR_IN_KEY;
+}
+
 static inline const char *btf_field_type_name(enum btf_field_type type)
 {
 	switch (type) {
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index d57bfb30463fa..07c67ad1a6a07 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1378,6 +1378,8 @@ static int map_create(union bpf_attr *attr)
 	if (err)
 		return -EINVAL;
 
+	if (attr->map_flags & BPF_INT_F_MASK)
+		return -EINVAL;
 	/* check BPF_F_TOKEN_FD flag, remember if it's set, and then clear it
 	 * to avoid per-map type checks tripping on unknown flag
 	 */
@@ -5057,7 +5059,7 @@ static int bpf_map_get_info_by_fd(struct file *file,
 	info.key_size = map->key_size;
 	info.value_size = map->value_size;
 	info.max_entries = map->max_entries;
-	info.map_flags = map->map_flags;
+	info.map_flags = map->map_flags & ~BPF_INT_F_MASK;
 	info.map_extra = map->map_extra;
 	memcpy(info.name, map->name, sizeof(map->name));
 
-- 
2.29.2





[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux