1 |
From foo@baz Thu Feb 17 08:07:01 PM CET 2022 |
2 |
From: Hao Luo <haoluo@google.com> |
3 |
Date: Wed, 16 Feb 2022 14:52:01 -0800 |
4 |
Subject: bpf: Introduce composable reg, ret and arg types. |
5 |
To: Greg KH <gregkh@linuxfoundation.org> |
6 |
Cc: Alexei Starovoitov <ast@kernel.org>, Andrii Nakryiko <andrii@kernel.org>, Daniel Borkmann <daniel@iogearbox.net>, laura@labbott.name, stable@vger.kernel.org, Hao Luo <haoluo@google.com> |
7 |
Message-ID: <20220216225209.2196865-2-haoluo@google.com> |
8 |
|
9 |
From: Hao Luo <haoluo@google.com> |
10 |
|
11 |
commit d639b9d13a39cf15639cbe6e8b2c43eb60148a73 upstream. |
12 |
|
13 |
There are some common properties shared between bpf reg, ret and arg |
14 |
values. For instance, a value may be a NULL pointer, or a pointer to |
15 |
a read-only memory. Previously, to express these properties, enumeration |
16 |
was used. For example, in order to test whether a reg value can be NULL, |
17 |
reg_type_may_be_null() simply enumerates all types that are possibly |
18 |
NULL. The problem of this approach is that it's not scalable and causes |
19 |
a lot of duplication. These properties can be combined, for example, a |
20 |
type could be either MAYBE_NULL or RDONLY, or both. |
21 |
|
22 |
This patch series rewrites the layout of reg_type, arg_type and |
23 |
ret_type, so that common properties can be extracted and represented as |
24 |
composable flag. For example, one can write |
25 |
|
26 |
ARG_PTR_TO_MEM | PTR_MAYBE_NULL |
27 |
|
28 |
which is equivalent to the previous |
29 |
|
30 |
ARG_PTR_TO_MEM_OR_NULL |
31 |
|
32 |
The type ARG_PTR_TO_MEM are called "base type" in this patch. Base |
33 |
types can be extended with flags. A flag occupies the higher bits while |
34 |
base types sits in the lower bits. |
35 |
|
36 |
This patch in particular sets up a set of macro for this purpose. The |
37 |
following patches will rewrite arg_types, ret_types and reg_types |
38 |
respectively. |
39 |
|
40 |
Signed-off-by: Hao Luo <haoluo@google.com> |
41 |
Signed-off-by: Alexei Starovoitov <ast@kernel.org> |
42 |
Link: https://lore.kernel.org/bpf/20211217003152.48334-2-haoluo@google.com |
43 |
Cc: stable@vger.kernel.org # 5.16.x |
44 |
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
45 |
--- |
46 |
include/linux/bpf.h | 42 ++++++++++++++++++++++++++++++++++++++++++ |
47 |
include/linux/bpf_verifier.h | 13 +++++++++++++ |
48 |
2 files changed, 55 insertions(+) |
49 |
|
50 |
--- a/include/linux/bpf.h |
51 |
+++ b/include/linux/bpf.h |
52 |
@@ -297,6 +297,29 @@ bool bpf_map_meta_equal(const struct bpf |
53 |
|
54 |
extern const struct bpf_map_ops bpf_map_offload_ops; |
55 |
|
56 |
+/* bpf_type_flag contains a set of flags that are applicable to the values of |
57 |
+ * arg_type, ret_type and reg_type. For example, a pointer value may be null, |
58 |
+ * or a memory is read-only. We classify types into two categories: base types |
59 |
+ * and extended types. Extended types are base types combined with a type flag. |
60 |
+ * |
61 |
+ * Currently there are no more than 32 base types in arg_type, ret_type and |
62 |
+ * reg_types. |
63 |
+ */ |
64 |
+#define BPF_BASE_TYPE_BITS 8 |
65 |
+ |
66 |
+enum bpf_type_flag { |
67 |
+ /* PTR may be NULL. */ |
68 |
+ PTR_MAYBE_NULL = BIT(0 + BPF_BASE_TYPE_BITS), |
69 |
+ |
70 |
+ __BPF_TYPE_LAST_FLAG = PTR_MAYBE_NULL, |
71 |
+}; |
72 |
+ |
73 |
+/* Max number of base types. */ |
74 |
+#define BPF_BASE_TYPE_LIMIT (1UL << BPF_BASE_TYPE_BITS) |
75 |
+ |
76 |
+/* Max number of all types. */ |
77 |
+#define BPF_TYPE_LIMIT (__BPF_TYPE_LAST_FLAG | (__BPF_TYPE_LAST_FLAG - 1)) |
78 |
+ |
79 |
/* function argument constraints */ |
80 |
enum bpf_arg_type { |
81 |
ARG_DONTCARE = 0, /* unused argument in helper function */ |
82 |
@@ -343,7 +366,13 @@ enum bpf_arg_type { |
83 |
ARG_PTR_TO_CONST_STR, /* pointer to a null terminated read-only string */ |
84 |
ARG_PTR_TO_TIMER, /* pointer to bpf_timer */ |
85 |
__BPF_ARG_TYPE_MAX, |
86 |
+ |
87 |
+ /* This must be the last entry. Its purpose is to ensure the enum is |
88 |
+ * wide enough to hold the higher bits reserved for bpf_type_flag. |
89 |
+ */ |
90 |
+ __BPF_ARG_TYPE_LIMIT = BPF_TYPE_LIMIT, |
91 |
}; |
92 |
+static_assert(__BPF_ARG_TYPE_MAX <= BPF_BASE_TYPE_LIMIT); |
93 |
|
94 |
/* type of values returned from helper functions */ |
95 |
enum bpf_return_type { |
96 |
@@ -359,7 +388,14 @@ enum bpf_return_type { |
97 |
RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL, /* returns a pointer to a valid memory or a btf_id or NULL */ |
98 |
RET_PTR_TO_MEM_OR_BTF_ID, /* returns a pointer to a valid memory or a btf_id */ |
99 |
RET_PTR_TO_BTF_ID, /* returns a pointer to a btf_id */ |
100 |
+ __BPF_RET_TYPE_MAX, |
101 |
+ |
102 |
+ /* This must be the last entry. Its purpose is to ensure the enum is |
103 |
+ * wide enough to hold the higher bits reserved for bpf_type_flag. |
104 |
+ */ |
105 |
+ __BPF_RET_TYPE_LIMIT = BPF_TYPE_LIMIT, |
106 |
}; |
107 |
+static_assert(__BPF_RET_TYPE_MAX <= BPF_BASE_TYPE_LIMIT); |
108 |
|
109 |
/* eBPF function prototype used by verifier to allow BPF_CALLs from eBPF programs |
110 |
* to in-kernel helper functions and for adjusting imm32 field in BPF_CALL |
111 |
@@ -461,7 +497,13 @@ enum bpf_reg_type { |
112 |
PTR_TO_FUNC, /* reg points to a bpf program function */ |
113 |
PTR_TO_MAP_KEY, /* reg points to a map element key */ |
114 |
__BPF_REG_TYPE_MAX, |
115 |
+ |
116 |
+ /* This must be the last entry. Its purpose is to ensure the enum is |
117 |
+ * wide enough to hold the higher bits reserved for bpf_type_flag. |
118 |
+ */ |
119 |
+ __BPF_REG_TYPE_LIMIT = BPF_TYPE_LIMIT, |
120 |
}; |
121 |
+static_assert(__BPF_REG_TYPE_MAX <= BPF_BASE_TYPE_LIMIT); |
122 |
|
123 |
/* The information passed from prog-specific *_is_valid_access |
124 |
* back to the verifier. |
125 |
--- a/include/linux/bpf_verifier.h |
126 |
+++ b/include/linux/bpf_verifier.h |
127 |
@@ -536,5 +536,18 @@ int bpf_check_attach_target(struct bpf_v |
128 |
struct bpf_attach_target_info *tgt_info); |
129 |
void bpf_free_kfunc_btf_tab(struct bpf_kfunc_btf_tab *tab); |
130 |
|
131 |
+#define BPF_BASE_TYPE_MASK GENMASK(BPF_BASE_TYPE_BITS - 1, 0) |
132 |
+ |
133 |
+/* extract base type from bpf_{arg, return, reg}_type. */ |
134 |
+static inline u32 base_type(u32 type) |
135 |
+{ |
136 |
+ return type & BPF_BASE_TYPE_MASK; |
137 |
+} |
138 |
+ |
139 |
+/* extract flags from an extended type. See bpf_type_flag in bpf.h. */ |
140 |
+static inline u32 type_flag(u32 type) |
141 |
+{ |
142 |
+ return type & ~BPF_BASE_TYPE_MASK; |
143 |
+} |
144 |
|
145 |
#endif /* _LINUX_BPF_VERIFIER_H */ |