]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ipv6: fix state corruption during proxy_ndp sysctl restart
authorFernando Fernandez Mancera <fmancera@suse.de>
Mon, 22 Jun 2026 13:08:56 +0000 (15:08 +0200)
committerJakub Kicinski <kuba@kernel.org>
Wed, 24 Jun 2026 02:12:47 +0000 (19:12 -0700)
When handling proxy_ndp, if rtnl_net_trylock() fails, the operation is
retried but as the value was already modified by the initial
proc_dointvec() call, the restarted syscall will read the newly modified
value as the 'old' state.

Fix this by taking the RTNL lock before parsing the input value if the
operation is a write.

Fixes: c92d5491a6d9 ("netconf: add support for IPv6 proxy_ndp")
Reviewed-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260622130857.5115-6-fmancera@suse.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv6/addrconf.c

index 5d96cbf76134a8aae20378f3450ef865aa6fc951..82b6f603faa04495da201d52ba7da8d2599ea03a 100644 (file)
@@ -6482,20 +6482,19 @@ static int addrconf_sysctl_disable(const struct ctl_table *ctl, int write,
 static int addrconf_sysctl_proxy_ndp(const struct ctl_table *ctl, int write,
                void *buffer, size_t *lenp, loff_t *ppos)
 {
+       struct net *net = ctl->extra2;
        int *valp = ctl->data;
-       int ret;
        int old, new;
+       int ret;
+
+       if (write && !rtnl_net_trylock(net))
+               return restart_syscall();
 
        old = *valp;
        ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
        new = *valp;
 
        if (write && old != new) {
-               struct net *net = ctl->extra2;
-
-               if (!rtnl_net_trylock(net))
-                       return restart_syscall();
-
                if (valp == &net->ipv6.devconf_dflt->proxy_ndp) {
                        inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
                                                     NETCONFA_PROXY_NEIGH,
@@ -6514,8 +6513,9 @@ static int addrconf_sysctl_proxy_ndp(const struct ctl_table *ctl, int write,
                                                     idev->dev->ifindex,
                                                     &idev->cnf);
                }
-               rtnl_net_unlock(net);
        }
+       if (write)
+               rtnl_net_unlock(net);
 
        return ret;
 }