From 5a6b25d2d11dcefb300c5c5e121358737fa750fc Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mar 03 2023 11:25:15 +0000 Subject: bpf: bpf_fib_lookup should not return neigh in NUD_FAILED state (bsc#1012628). --- diff --git a/patches.kernel.org/6.2.2-003-bpf-bpf_fib_lookup-should-not-return-neigh-in-N.patch b/patches.kernel.org/6.2.2-003-bpf-bpf_fib_lookup-should-not-return-neigh-in-N.patch new file mode 100644 index 0000000..38d8809 --- /dev/null +++ b/patches.kernel.org/6.2.2-003-bpf-bpf_fib_lookup-should-not-return-neigh-in-N.patch @@ -0,0 +1,55 @@ +From: Martin KaFai Lau +Date: Thu, 16 Feb 2023 16:41:48 -0800 +Subject: [PATCH] bpf: bpf_fib_lookup should not return neigh in NUD_FAILED + state +References: bsc#1012628 +Patch-mainline: 6.2.2 +Git-commit: 1fe4850b34ab512ff911e2c035c75fb6438f7307 + +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 +Signed-off-by: Daniel Borkmann +Link: https://lore.kernel.org/bpf/20230217004150.2980689-3-martin.lau@linux.dev +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Jiri Slaby +--- + net/core/filter.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/core/filter.c b/net/core/filter.c +index 43cc1fe5..a00a4b54 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -5816,7 +5816,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, mtu); +@@ -5931,7 +5931,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, mtu); +-- +2.35.3 + diff --git a/series.conf b/series.conf index b6d526c..6b771f7 100644 --- a/series.conf +++ b/series.conf @@ -42,6 +42,7 @@ patches.kernel.org/6.2.1-013-Linux-6.2.1.patch patches.kernel.org/6.2.2-001-ALSA-hda-cs35l41-Correct-error-condition-handli.patch patches.kernel.org/6.2.2-002-crypto-arm64-sm4-gcm-Fix-possible-crash-in-GCM-.patch + patches.kernel.org/6.2.2-003-bpf-bpf_fib_lookup-should-not-return-neigh-in-N.patch ######################################################## # Build fixes that apply to the vanilla kernel too.