Skip to content

Commit d639b9d

Browse files
haoluo1022Alexei Starovoitov
authored andcommitted
bpf: Introduce composable reg, ret and arg types.
There are some common properties shared between bpf reg, ret and arg values. For instance, a value may be a NULL pointer, or a pointer to a read-only memory. Previously, to express these properties, enumeration was used. For example, in order to test whether a reg value can be NULL, reg_type_may_be_null() simply enumerates all types that are possibly NULL. The problem of this approach is that it's not scalable and causes a lot of duplication. These properties can be combined, for example, a type could be either MAYBE_NULL or RDONLY, or both. This patch series rewrites the layout of reg_type, arg_type and ret_type, so that common properties can be extracted and represented as composable flag. For example, one can write ARG_PTR_TO_MEM | PTR_MAYBE_NULL which is equivalent to the previous ARG_PTR_TO_MEM_OR_NULL The type ARG_PTR_TO_MEM are called "base type" in this patch. Base types can be extended with flags. A flag occupies the higher bits while base types sits in the lower bits. This patch in particular sets up a set of macro for this purpose. The following patches will rewrite arg_types, ret_types and reg_types respectively. Signed-off-by: Hao Luo <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent e967a20 commit d639b9d

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

include/linux/bpf.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,29 @@ bool bpf_map_meta_equal(const struct bpf_map *meta0,
297297

298298
extern const struct bpf_map_ops bpf_map_offload_ops;
299299

300+
/* bpf_type_flag contains a set of flags that are applicable to the values of
301+
* arg_type, ret_type and reg_type. For example, a pointer value may be null,
302+
* or a memory is read-only. We classify types into two categories: base types
303+
* and extended types. Extended types are base types combined with a type flag.
304+
*
305+
* Currently there are no more than 32 base types in arg_type, ret_type and
306+
* reg_types.
307+
*/
308+
#define BPF_BASE_TYPE_BITS 8
309+
310+
enum bpf_type_flag {
311+
/* PTR may be NULL. */
312+
PTR_MAYBE_NULL = BIT(0 + BPF_BASE_TYPE_BITS),
313+
314+
__BPF_TYPE_LAST_FLAG = PTR_MAYBE_NULL,
315+
};
316+
317+
/* Max number of base types. */
318+
#define BPF_BASE_TYPE_LIMIT (1UL << BPF_BASE_TYPE_BITS)
319+
320+
/* Max number of all types. */
321+
#define BPF_TYPE_LIMIT (__BPF_TYPE_LAST_FLAG | (__BPF_TYPE_LAST_FLAG - 1))
322+
300323
/* function argument constraints */
301324
enum bpf_arg_type {
302325
ARG_DONTCARE = 0, /* unused argument in helper function */
@@ -343,7 +366,13 @@ enum bpf_arg_type {
343366
ARG_PTR_TO_CONST_STR, /* pointer to a null terminated read-only string */
344367
ARG_PTR_TO_TIMER, /* pointer to bpf_timer */
345368
__BPF_ARG_TYPE_MAX,
369+
370+
/* This must be the last entry. Its purpose is to ensure the enum is
371+
* wide enough to hold the higher bits reserved for bpf_type_flag.
372+
*/
373+
__BPF_ARG_TYPE_LIMIT = BPF_TYPE_LIMIT,
346374
};
375+
static_assert(__BPF_ARG_TYPE_MAX <= BPF_BASE_TYPE_LIMIT);
347376

348377
/* type of values returned from helper functions */
349378
enum bpf_return_type {
@@ -359,7 +388,14 @@ enum bpf_return_type {
359388
RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL, /* returns a pointer to a valid memory or a btf_id or NULL */
360389
RET_PTR_TO_MEM_OR_BTF_ID, /* returns a pointer to a valid memory or a btf_id */
361390
RET_PTR_TO_BTF_ID, /* returns a pointer to a btf_id */
391+
__BPF_RET_TYPE_MAX,
392+
393+
/* This must be the last entry. Its purpose is to ensure the enum is
394+
* wide enough to hold the higher bits reserved for bpf_type_flag.
395+
*/
396+
__BPF_RET_TYPE_LIMIT = BPF_TYPE_LIMIT,
362397
};
398+
static_assert(__BPF_RET_TYPE_MAX <= BPF_BASE_TYPE_LIMIT);
363399

364400
/* eBPF function prototype used by verifier to allow BPF_CALLs from eBPF programs
365401
* to in-kernel helper functions and for adjusting imm32 field in BPF_CALL
@@ -461,7 +497,13 @@ enum bpf_reg_type {
461497
PTR_TO_FUNC, /* reg points to a bpf program function */
462498
PTR_TO_MAP_KEY, /* reg points to a map element key */
463499
__BPF_REG_TYPE_MAX,
500+
501+
/* This must be the last entry. Its purpose is to ensure the enum is
502+
* wide enough to hold the higher bits reserved for bpf_type_flag.
503+
*/
504+
__BPF_REG_TYPE_LIMIT = BPF_TYPE_LIMIT,
464505
};
506+
static_assert(__BPF_REG_TYPE_MAX <= BPF_BASE_TYPE_LIMIT);
465507

466508
/* The information passed from prog-specific *_is_valid_access
467509
* back to the verifier.

include/linux/bpf_verifier.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,5 +546,18 @@ int bpf_check_attach_target(struct bpf_verifier_log *log,
546546
struct bpf_attach_target_info *tgt_info);
547547
void bpf_free_kfunc_btf_tab(struct bpf_kfunc_btf_tab *tab);
548548

549+
#define BPF_BASE_TYPE_MASK GENMASK(BPF_BASE_TYPE_BITS - 1, 0)
550+
551+
/* extract base type from bpf_{arg, return, reg}_type. */
552+
static inline u32 base_type(u32 type)
553+
{
554+
return type & BPF_BASE_TYPE_MASK;
555+
}
556+
557+
/* extract flags from an extended type. See bpf_type_flag in bpf.h. */
558+
static inline u32 type_flag(u32 type)
559+
{
560+
return type & ~BPF_BASE_TYPE_MASK;
561+
}
549562

550563
#endif /* _LINUX_BPF_VERIFIER_H */

0 commit comments

Comments
 (0)