summaryrefslogtreecommitdiff
path: root/net/core
diff options
context:
space:
mode:
authorMartin KaFai Lau <martin.lau@kernel.org>2023-02-17 03:41:48 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-03-03 13:44:51 +0300
commita2957adbf3f5450f7425c545863da4a3287e06a1 (patch)
tree36ed7ad3c5e14da029e69032a5942ac16f03eab0 /net/core
parent75fbe1e43505f3474d6f590314671e0e53a2afa7 (diff)
downloadlinux-a2957adbf3f5450f7425c545863da4a3287e06a1.tar.xz
bpf: bpf_fib_lookup should not return neigh in NUD_FAILED state
commit 1fe4850b34ab512ff911e2c035c75fb6438f7307 upstream. The bpf_fib_lookup() helper does not only look up the fib (ie. route) but it also looks up the neigh. Before returning the neigh, the helper does not check for NUD_VALID. When a neigh state (neigh->nud_state) is in NUD_FAILED, its dmac (neigh->ha) could be all zeros. The helper still returns SUCCESS instead of NO_NEIGH in this case. Because of the SUCCESS return value, the bpf prog directly uses the returned dmac and ends up filling all zero in the eth header. This patch checks for NUD_VALID and returns NO_NEIGH if the neigh is not valid. Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Link: https://lore.kernel.org/bpf/20230217004150.2980689-3-martin.lau@linux.dev Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/filter.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/net/core/filter.c b/net/core/filter.c
index a5df0cf46bbf..b9c954182b37 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -5401,7 +5401,7 @@ static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
neigh = __ipv6_neigh_lookup_noref_stub(dev, dst);
}
- if (!neigh)
+ if (!neigh || !(neigh->nud_state & NUD_VALID))
return BPF_FIB_LKUP_RET_NO_NEIGH;
return bpf_fib_set_fwd_params(params, neigh, dev);
@@ -5514,7 +5514,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
* not needed here.
*/
neigh = __ipv6_neigh_lookup_noref_stub(dev, dst);
- if (!neigh)
+ if (!neigh || !(neigh->nud_state & NUD_VALID))
return BPF_FIB_LKUP_RET_NO_NEIGH;
return bpf_fib_set_fwd_params(params, neigh, dev);