]>
Commit | Line | Data |
---|---|---|
36e3f504 SL |
1 | From b767f332f8defabc623af4217793f028897be730 Mon Sep 17 00:00:00 2001 |
2 | From: Alban Crequy <alban@kinvolk.io> | |
3 | Date: Fri, 22 Feb 2019 14:19:08 +0100 | |
4 | Subject: bpf, lpm: fix lookup bug in map_delete_elem | |
5 | ||
6 | [ Upstream commit 7c0cdf0b3940f63d9777c3fcf250a2f83859ca54 ] | |
7 | ||
8 | trie_delete_elem() was deleting an entry even though it was not matching | |
9 | if the prefixlen was correct. This patch adds a check on matchlen. | |
10 | ||
11 | Reproducer: | |
12 | ||
13 | $ sudo bpftool map create /sys/fs/bpf/mylpm type lpm_trie key 8 value 1 entries 128 name mylpm flags 1 | |
14 | $ sudo bpftool map update pinned /sys/fs/bpf/mylpm key hex 10 00 00 00 aa bb cc dd value hex 01 | |
15 | $ sudo bpftool map dump pinned /sys/fs/bpf/mylpm | |
16 | key: 10 00 00 00 aa bb cc dd value: 01 | |
17 | Found 1 element | |
18 | $ sudo bpftool map delete pinned /sys/fs/bpf/mylpm key hex 10 00 00 00 ff ff ff ff | |
19 | $ echo $? | |
20 | 0 | |
21 | $ sudo bpftool map dump pinned /sys/fs/bpf/mylpm | |
22 | Found 0 elements | |
23 | ||
24 | A similar reproducer is added in the selftests. | |
25 | ||
26 | Without the patch: | |
27 | ||
28 | $ sudo ./tools/testing/selftests/bpf/test_lpm_map | |
29 | test_lpm_map: test_lpm_map.c:485: test_lpm_delete: Assertion `bpf_map_delete_elem(map_fd, key) == -1 && errno == ENOENT' failed. | |
30 | Aborted | |
31 | ||
32 | With the patch: test_lpm_map runs without errors. | |
33 | ||
34 | Fixes: e454cf595853 ("bpf: Implement map_delete_elem for BPF_MAP_TYPE_LPM_TRIE") | |
35 | Cc: Craig Gallek <kraig@google.com> | |
36 | Signed-off-by: Alban Crequy <alban@kinvolk.io> | |
37 | Acked-by: Craig Gallek <kraig@google.com> | |
38 | Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> | |
39 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
40 | --- | |
41 | kernel/bpf/lpm_trie.c | 1 + | |
42 | tools/testing/selftests/bpf/test_lpm_map.c | 10 ++++++++++ | |
43 | 2 files changed, 11 insertions(+) | |
44 | ||
45 | diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c | |
46 | index 9058317ba9de..4f3138e6ecb2 100644 | |
47 | --- a/kernel/bpf/lpm_trie.c | |
48 | +++ b/kernel/bpf/lpm_trie.c | |
49 | @@ -432,6 +432,7 @@ static int trie_delete_elem(struct bpf_map *map, void *_key) | |
50 | } | |
51 | ||
52 | if (!node || node->prefixlen != key->prefixlen || | |
53 | + node->prefixlen != matchlen || | |
54 | (node->flags & LPM_TREE_NODE_FLAG_IM)) { | |
55 | ret = -ENOENT; | |
56 | goto out; | |
57 | diff --git a/tools/testing/selftests/bpf/test_lpm_map.c b/tools/testing/selftests/bpf/test_lpm_map.c | |
58 | index 147e34cfceb7..02d7c871862a 100644 | |
59 | --- a/tools/testing/selftests/bpf/test_lpm_map.c | |
60 | +++ b/tools/testing/selftests/bpf/test_lpm_map.c | |
61 | @@ -474,6 +474,16 @@ static void test_lpm_delete(void) | |
62 | assert(bpf_map_lookup_elem(map_fd, key, &value) == -1 && | |
63 | errno == ENOENT); | |
64 | ||
65 | + key->prefixlen = 30; // unused prefix so far | |
66 | + inet_pton(AF_INET, "192.255.0.0", key->data); | |
67 | + assert(bpf_map_delete_elem(map_fd, key) == -1 && | |
68 | + errno == ENOENT); | |
69 | + | |
70 | + key->prefixlen = 16; // same prefix as the root node | |
71 | + inet_pton(AF_INET, "192.255.0.0", key->data); | |
72 | + assert(bpf_map_delete_elem(map_fd, key) == -1 && | |
73 | + errno == ENOENT); | |
74 | + | |
75 | /* assert initial lookup */ | |
76 | key->prefixlen = 32; | |
77 | inet_pton(AF_INET, "192.168.0.1", key->data); | |
78 | -- | |
79 | 2.19.1 | |
80 |