From 05091e429e5e6833eea25f1caa5f7e456144307c Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Mon, 15 Nov 2021 08:42:05 -0500 Subject: [PATCH] Fixes for 5.15 Signed-off-by: Sasha Levin --- ...-state-migration-between-nud_permane.patch | 163 ++++++++++++++++++ queue-5.15/series | 1 + 2 files changed, 164 insertions(+) create mode 100644 queue-5.15/net-neigh-enable-state-migration-between-nud_permane.patch diff --git a/queue-5.15/net-neigh-enable-state-migration-between-nud_permane.patch b/queue-5.15/net-neigh-enable-state-migration-between-nud_permane.patch new file mode 100644 index 00000000000..d72acb92d57 --- /dev/null +++ b/queue-5.15/net-neigh-enable-state-migration-between-nud_permane.patch @@ -0,0 +1,163 @@ +From f153e32baca20753efb9d3865c1d9c54b9713eef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Oct 2021 14:12:36 +0200 +Subject: net, neigh: Enable state migration between NUD_PERMANENT and NTF_USE + +From: Daniel Borkmann + +[ Upstream commit 3dc20f4762c62d3b3f0940644881ed818aa7b2f5 ] + +Currently, it is not possible to migrate a neighbor entry between NUD_PERMANENT +state and NTF_USE flag with a dynamic NUD state from a user space control plane. +Similarly, it is not possible to add/remove NTF_EXT_LEARNED flag from an existing +neighbor entry in combination with NTF_USE flag. + +This is due to the latter directly calling into neigh_event_send() without any +meta data updates as happening in __neigh_update(). Thus, to enable this use +case, extend the latter with a NEIGH_UPDATE_F_USE flag where we break the +NUD_PERMANENT state in particular so that a latter neigh_event_send() is able +to re-resolve a neighbor entry. + +Before fix, NUD_PERMANENT -> NUD_* & NTF_USE: + + # ./ip/ip n replace 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a PERMANENT + [...] + # ./ip/ip n replace 192.168.178.30 dev enp5s0 use extern_learn + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a PERMANENT + [...] + +As can be seen, despite the admin-triggered replace, the entry remains in the +NUD_PERMANENT state. + +After fix, NUD_PERMANENT -> NUD_* & NTF_USE: + + # ./ip/ip n replace 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a PERMANENT + [...] + # ./ip/ip n replace 192.168.178.30 dev enp5s0 use extern_learn + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a extern_learn REACHABLE + [...] + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a extern_learn STALE + [...] + # ./ip/ip n replace 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a PERMANENT + [...] + +After the fix, the admin-triggered replace switches to a dynamic state from +the NTF_USE flag which triggered a new neighbor resolution. Likewise, we can +transition back from there, if needed, into NUD_PERMANENT. + +Similar before/after behavior can be observed for below transitions: + +Before fix, NTF_USE -> NTF_USE | NTF_EXT_LEARNED -> NTF_USE: + + # ./ip/ip n replace 192.168.178.30 dev enp5s0 use + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a REACHABLE + [...] + # ./ip/ip n replace 192.168.178.30 dev enp5s0 use extern_learn + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a REACHABLE + [...] + +After fix, NTF_USE -> NTF_USE | NTF_EXT_LEARNED -> NTF_USE: + + # ./ip/ip n replace 192.168.178.30 dev enp5s0 use + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a REACHABLE + [...] + # ./ip/ip n replace 192.168.178.30 dev enp5s0 use extern_learn + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a extern_learn REACHABLE + [...] + # ./ip/ip n replace 192.168.178.30 dev enp5s0 use + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a REACHABLE + [..] + +Signed-off-by: Daniel Borkmann +Acked-by: Roopa Prabhu +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + include/net/neighbour.h | 1 + + net/core/neighbour.c | 22 +++++++++++++--------- + 2 files changed, 14 insertions(+), 9 deletions(-) + +diff --git a/include/net/neighbour.h b/include/net/neighbour.h +index 990f9b1d17092..d5767e25509cc 100644 +--- a/include/net/neighbour.h ++++ b/include/net/neighbour.h +@@ -253,6 +253,7 @@ static inline void *neighbour_priv(const struct neighbour *n) + #define NEIGH_UPDATE_F_OVERRIDE 0x00000001 + #define NEIGH_UPDATE_F_WEAK_OVERRIDE 0x00000002 + #define NEIGH_UPDATE_F_OVERRIDE_ISROUTER 0x00000004 ++#define NEIGH_UPDATE_F_USE 0x10000000 + #define NEIGH_UPDATE_F_EXT_LEARNED 0x20000000 + #define NEIGH_UPDATE_F_ISROUTER 0x40000000 + #define NEIGH_UPDATE_F_ADMIN 0x80000000 +diff --git a/net/core/neighbour.c b/net/core/neighbour.c +index 8457d5f97022b..3e58037a8ae6f 100644 +--- a/net/core/neighbour.c ++++ b/net/core/neighbour.c +@@ -1217,7 +1217,7 @@ static void neigh_update_hhs(struct neighbour *neigh) + lladdr instead of overriding it + if it is different. + NEIGH_UPDATE_F_ADMIN means that the change is administrative. +- ++ NEIGH_UPDATE_F_USE means that the entry is user triggered. + NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing + NTF_ROUTER flag. + NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as +@@ -1255,6 +1255,12 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr, + goto out; + + ext_learn_change = neigh_update_ext_learned(neigh, flags, ¬ify); ++ if (flags & NEIGH_UPDATE_F_USE) { ++ new = old & ~NUD_PERMANENT; ++ neigh->nud_state = new; ++ err = 0; ++ goto out; ++ } + + if (!(new & NUD_VALID)) { + neigh_del_timer(neigh); +@@ -1963,22 +1969,20 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, + + if (protocol) + neigh->protocol = protocol; +- + if (ndm->ndm_flags & NTF_EXT_LEARNED) + flags |= NEIGH_UPDATE_F_EXT_LEARNED; +- + if (ndm->ndm_flags & NTF_ROUTER) + flags |= NEIGH_UPDATE_F_ISROUTER; ++ if (ndm->ndm_flags & NTF_USE) ++ flags |= NEIGH_UPDATE_F_USE; + +- if (ndm->ndm_flags & NTF_USE) { ++ err = __neigh_update(neigh, lladdr, ndm->ndm_state, flags, ++ NETLINK_CB(skb).portid, extack); ++ if (!err && ndm->ndm_flags & NTF_USE) { + neigh_event_send(neigh, NULL); + err = 0; +- } else +- err = __neigh_update(neigh, lladdr, ndm->ndm_state, flags, +- NETLINK_CB(skb).portid, extack); +- ++ } + neigh_release(neigh); +- + out: + return err; + } +-- +2.33.0 + diff --git a/queue-5.15/series b/queue-5.15/series index 1825bbdb3e4..d7078ff183d 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -857,3 +857,4 @@ x86-mce-add-errata-workaround-for-skylake-skx37.patch pci-msi-move-non-mask-check-back-into-low-level-accessors.patch pci-msi-destroy-sysfs-before-freeing-entries.patch kvm-x86-move-guest_pv_has-out-of-user_access-section.patch +net-neigh-enable-state-migration-between-nud_permane.patch -- 2.47.2