]>
Commit | Line | Data |
---|---|---|
877e0084 GKH |
1 | From 80f1d68ccba70b1060c9c7360ca83da430f66bed Mon Sep 17 00:00:00 2001 |
2 | From: Daniel Borkmann <daniel@iogearbox.net> | |
3 | Date: Thu, 12 Mar 2015 17:21:42 +0100 | |
4 | Subject: ebpf: verifier: check that call reg with ARG_ANYTHING is initialized | |
5 | ||
6 | From: Daniel Borkmann <daniel@iogearbox.net> | |
7 | ||
8 | commit 80f1d68ccba70b1060c9c7360ca83da430f66bed upstream. | |
9 | ||
10 | I noticed that a helper function with argument type ARG_ANYTHING does | |
11 | not need to have an initialized value (register). | |
12 | ||
13 | This can worst case lead to unintented stack memory leakage in future | |
14 | helper functions if they are not carefully designed, or unintended | |
15 | application behaviour in case the application developer was not careful | |
16 | enough to match a correct helper function signature in the API. | |
17 | ||
18 | The underlying issue is that ARG_ANYTHING should actually be split | |
19 | into two different semantics: | |
20 | ||
21 | 1) ARG_DONTCARE for function arguments that the helper function | |
22 | does not care about (in other words: the default for unused | |
23 | function arguments), and | |
24 | ||
25 | 2) ARG_ANYTHING that is an argument actually being used by a | |
26 | helper function and *guaranteed* to be an initialized register. | |
27 | ||
28 | The current risk is low: ARG_ANYTHING is only used for the 'flags' | |
29 | argument (r4) in bpf_map_update_elem() that internally does strict | |
30 | checking. | |
31 | ||
32 | Fixes: 17a5267067f3 ("bpf: verifier (add verifier core)") | |
33 | Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> | |
34 | Acked-by: Alexei Starovoitov <ast@plumgrid.com> | |
35 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
36 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
37 | ||
38 | --- | |
39 | include/linux/bpf.h | 4 +++- | |
40 | kernel/bpf/verifier.c | 5 ++++- | |
41 | 2 files changed, 7 insertions(+), 2 deletions(-) | |
42 | ||
43 | --- a/include/linux/bpf.h | |
44 | +++ b/include/linux/bpf.h | |
45 | @@ -48,7 +48,7 @@ struct bpf_map *bpf_map_get(struct fd f) | |
46 | ||
47 | /* function argument constraints */ | |
48 | enum bpf_arg_type { | |
49 | - ARG_ANYTHING = 0, /* any argument is ok */ | |
50 | + ARG_DONTCARE = 0, /* unused argument in helper function */ | |
51 | ||
52 | /* the following constraints used to prototype | |
53 | * bpf_map_lookup/update/delete_elem() functions | |
54 | @@ -62,6 +62,8 @@ enum bpf_arg_type { | |
55 | */ | |
56 | ARG_PTR_TO_STACK, /* any pointer to eBPF program stack */ | |
57 | ARG_CONST_STACK_SIZE, /* number of bytes accessed from stack */ | |
58 | + | |
59 | + ARG_ANYTHING, /* any (initialized) argument is ok */ | |
60 | }; | |
61 | ||
62 | /* type of values returned from helper functions */ | |
63 | --- a/kernel/bpf/verifier.c | |
64 | +++ b/kernel/bpf/verifier.c | |
65 | @@ -755,7 +755,7 @@ static int check_func_arg(struct verifie | |
66 | enum bpf_reg_type expected_type; | |
67 | int err = 0; | |
68 | ||
69 | - if (arg_type == ARG_ANYTHING) | |
70 | + if (arg_type == ARG_DONTCARE) | |
71 | return 0; | |
72 | ||
73 | if (reg->type == NOT_INIT) { | |
74 | @@ -763,6 +763,9 @@ static int check_func_arg(struct verifie | |
75 | return -EACCES; | |
76 | } | |
77 | ||
78 | + if (arg_type == ARG_ANYTHING) | |
79 | + return 0; | |
80 | + | |
81 | if (arg_type == ARG_PTR_TO_STACK || arg_type == ARG_PTR_TO_MAP_KEY || | |
82 | arg_type == ARG_PTR_TO_MAP_VALUE) { | |
83 | expected_type = PTR_TO_STACK; |