aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2024-02-15 17:21:06 +0000
committerDavid S. Miller <davem@davemloft.net>2024-02-18 10:22:27 +0000
commit081a0e3b0d4c061419d3f4679dec9f68725b17e4 (patch)
treef17704eaff8487f821301435f259bc835454b8bc
parent97dde84026339e4b4af9a6301f825d1828d7874b (diff)
downloadlinux-081a0e3b0d4c061419d3f4679dec9f68725b17e4.tar.gz
ipv4: properly combine dev_base_seq and ipv4.dev_addr_genid
net->dev_base_seq and ipv4.dev_addr_genid are monotonically increasing. If we XOR their values, we could miss to detect if both values were changed with the same amount. Fixes: 0465277f6b3f ("ipv4: provide addr and netconf dump consistency info") Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com> Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Notes
Fixes: 0465277f6b3f ("ipv4: provide addr and netconf dump consistency info") # v3.10-rc1 Stable: 6634a8ecacc6 # v6.6.19 Stable: b43a4fb42fef # v6.1.80 Stable: a75b49547831 # v5.15.150 Stable: dcc1375d41a0 # v5.10.211 Stable: 5888f3424907 # v5.4.270 Lore: https://lore.kernel.org/r/20240215172107.3461054-2-edumazet@google.com # netdev Lore: https://lore.kernel.org/r/20240227131555.180507987@linuxfoundation.org # linux-patches, stable Lore: https://lore.kernel.org/r/20240227131602.141630918@linuxfoundation.org # linux-patches, stable Lore: https://lore.kernel.org/r/20240227131615.505167092@linuxfoundation.org # linux-patches, stable Lore: https://lore.kernel.org/r/20240227131622.195048004@linuxfoundation.org # linux-patches, stable Lore: https://lore.kernel.org/r/20240227131633.609885709@linuxfoundation.org # linux-patches, stable Lore: https://lore.kernel.org/r/20240227131639.667440244@linuxfoundation.org # linux-patches, stable
-rw-r--r--net/ipv4/devinet.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index ca0ff15dc8fa3..bc74f131fe4df 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1825,6 +1825,21 @@ done:
return err;
}
+/* Combine dev_addr_genid and dev_base_seq to detect changes.
+ */
+static u32 inet_base_seq(const struct net *net)
+{
+ u32 res = atomic_read(&net->ipv4.dev_addr_genid) +
+ net->dev_base_seq;
+
+ /* Must not return 0 (see nl_dump_check_consistent()).
+ * Chose a value far away from 0.
+ */
+ if (!res)
+ res = 0x80000000;
+ return res;
+}
+
static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
{
const struct nlmsghdr *nlh = cb->nlh;
@@ -1876,8 +1891,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
idx = 0;
head = &tgt_net->dev_index_head[h];
rcu_read_lock();
- cb->seq = atomic_read(&tgt_net->ipv4.dev_addr_genid) ^
- tgt_net->dev_base_seq;
+ cb->seq = inet_base_seq(tgt_net);
hlist_for_each_entry_rcu(dev, head, index_hlist) {
if (idx < s_idx)
goto cont;
@@ -2278,8 +2292,7 @@ static int inet_netconf_dump_devconf(struct sk_buff *skb,
idx = 0;
head = &net->dev_index_head[h];
rcu_read_lock();
- cb->seq = atomic_read(&net->ipv4.dev_addr_genid) ^
- net->dev_base_seq;
+ cb->seq = inet_base_seq(net);
hlist_for_each_entry_rcu(dev, head, index_hlist) {
if (idx < s_idx)
goto cont;