Skip to content

Commit 57c3bb7

Browse files
rdnaAlexei Starovoitov
authored and
Alexei Starovoitov
committed
bpf: Introduce ARG_PTR_TO_{INT,LONG} arg types
Currently the way to pass result from BPF helper to BPF program is to provide memory area defined by pointer and size: func(void *, size_t). It works great for generic use-case, but for simple types, such as int, it's overkill and consumes two arguments when it could use just one. Introduce new argument types ARG_PTR_TO_INT and ARG_PTR_TO_LONG to be able to pass result from helper to program via pointer to int and long correspondingly: func(int *) or func(long *). New argument types are similar to ARG_PTR_TO_MEM with the following differences: * they don't require corresponding ARG_CONST_SIZE argument, predefined access sizes are used instead (32bit for int, 64bit for long); * it's possible to use more than one such an argument in a helper; * provided pointers have to be aligned. It's easy to introduce similar ARG_PTR_TO_CHAR and ARG_PTR_TO_SHORT argument types. It's not done due to lack of use-case though. Signed-off-by: Andrey Ignatov <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 9a1027e commit 57c3bb7

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

include/linux/bpf.h

+2
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ enum bpf_arg_type {
202202
ARG_ANYTHING, /* any (initialized) argument is ok */
203203
ARG_PTR_TO_SPIN_LOCK, /* pointer to bpf_spin_lock */
204204
ARG_PTR_TO_SOCK_COMMON, /* pointer to sock_common */
205+
ARG_PTR_TO_INT, /* pointer to int */
206+
ARG_PTR_TO_LONG, /* pointer to long */
205207
};
206208

207209
/* type of values returned from helper functions */

kernel/bpf/verifier.c

+29
Original file line numberDiff line numberDiff line change
@@ -2462,6 +2462,22 @@ static bool arg_type_is_mem_size(enum bpf_arg_type type)
24622462
type == ARG_CONST_SIZE_OR_ZERO;
24632463
}
24642464

2465+
static bool arg_type_is_int_ptr(enum bpf_arg_type type)
2466+
{
2467+
return type == ARG_PTR_TO_INT ||
2468+
type == ARG_PTR_TO_LONG;
2469+
}
2470+
2471+
static int int_ptr_type_to_size(enum bpf_arg_type type)
2472+
{
2473+
if (type == ARG_PTR_TO_INT)
2474+
return sizeof(u32);
2475+
else if (type == ARG_PTR_TO_LONG)
2476+
return sizeof(u64);
2477+
2478+
return -EINVAL;
2479+
}
2480+
24652481
static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
24662482
enum bpf_arg_type arg_type,
24672483
struct bpf_call_arg_meta *meta)
@@ -2554,6 +2570,12 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
25542570
type != expected_type)
25552571
goto err_type;
25562572
meta->raw_mode = arg_type == ARG_PTR_TO_UNINIT_MEM;
2573+
} else if (arg_type_is_int_ptr(arg_type)) {
2574+
expected_type = PTR_TO_STACK;
2575+
if (!type_is_pkt_pointer(type) &&
2576+
type != PTR_TO_MAP_VALUE &&
2577+
type != expected_type)
2578+
goto err_type;
25572579
} else {
25582580
verbose(env, "unsupported arg_type %d\n", arg_type);
25592581
return -EFAULT;
@@ -2635,6 +2657,13 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
26352657
err = check_helper_mem_access(env, regno - 1,
26362658
reg->umax_value,
26372659
zero_size_allowed, meta);
2660+
} else if (arg_type_is_int_ptr(arg_type)) {
2661+
int size = int_ptr_type_to_size(arg_type);
2662+
2663+
err = check_helper_mem_access(env, regno, size, false, meta);
2664+
if (err)
2665+
return err;
2666+
err = check_ptr_alignment(env, reg, 0, size, true);
26382667
}
26392668

26402669
return err;

0 commit comments

Comments
 (0)