diff options
author | Daniel Borkmann <daniel@iogearbox.net> | 2015-03-12 17:21:42 +0100 |
---|---|---|
committer | Sasha Levin <sasha.levin@oracle.com> | 2015-05-17 19:12:27 -0400 |
commit | b6c65e367249dd9ddc28b4f49b171f6803d70266 (patch) | |
tree | 8a9a621c8a6071653b5103012f6d9fd4ad33547b /kernel | |
parent | fcea4d66b0d0660439f6a2eb5b3894d7ee5fd136 (diff) | |
download | lwn-b6c65e367249dd9ddc28b4f49b171f6803d70266.tar.gz lwn-b6c65e367249dd9ddc28b4f49b171f6803d70266.zip |
ebpf: verifier: check that call reg with ARG_ANYTHING is initialized
[ Upstream commit 80f1d68ccba70b1060c9c7360ca83da430f66bed ]
I noticed that a helper function with argument type ARG_ANYTHING does
not need to have an initialized value (register).
This can worst case lead to unintented stack memory leakage in future
helper functions if they are not carefully designed, or unintended
application behaviour in case the application developer was not careful
enough to match a correct helper function signature in the API.
The underlying issue is that ARG_ANYTHING should actually be split
into two different semantics:
1) ARG_DONTCARE for function arguments that the helper function
does not care about (in other words: the default for unused
function arguments), and
2) ARG_ANYTHING that is an argument actually being used by a
helper function and *guaranteed* to be an initialized register.
The current risk is low: ARG_ANYTHING is only used for the 'flags'
argument (r4) in bpf_map_update_elem() that internally does strict
checking.
Fixes: 17a5267067f3 ("bpf: verifier (add verifier core)")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/bpf/verifier.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index d8dcc80472c1..055ae6ac0280 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -763,7 +763,7 @@ static int check_func_arg(struct verifier_env *env, u32 regno, enum bpf_reg_type expected_type; int err = 0; - if (arg_type == ARG_ANYTHING) + if (arg_type == ARG_DONTCARE) return 0; if (reg->type == NOT_INIT) { @@ -771,6 +771,9 @@ static int check_func_arg(struct verifier_env *env, u32 regno, return -EACCES; } + if (arg_type == ARG_ANYTHING) + return 0; + if (arg_type == ARG_PTR_TO_STACK || arg_type == ARG_PTR_TO_MAP_KEY || arg_type == ARG_PTR_TO_MAP_VALUE) { expected_type = PTR_TO_STACK; |