Skip to content

Commit

Permalink
net: Fix sysctl restarts...
Browse files Browse the repository at this point in the history
Yuck.  It turns out that when we restart sysctls we were restarting
with the values already changed.  Which unfortunately meant that
the second time through we thought there was no change and skipped
all kinds of work, despite the fact that there was indeed a change.

I have fixed this the simplest way possible by restoring the changed
values when we restart the sysctl write.

One of my coworkers spotted this bug when after disabling forwarding
on an interface pings were still forwarded.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
ebiederm authored and davem330 committed Feb 19, 2010
1 parent b0483e7 commit 88af182
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 3 deletions.
7 changes: 6 additions & 1 deletion net/ipv4/devinet.c
Expand Up @@ -1317,14 +1317,19 @@ static int devinet_sysctl_forward(ctl_table *ctl, int write,
{
int *valp = ctl->data;
int val = *valp;
loff_t pos = *ppos;
int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);

if (write && *valp != val) {
struct net *net = ctl->extra2;

if (valp != &IPV4_DEVCONF_DFLT(net, FORWARDING)) {
if (!rtnl_trylock())
if (!rtnl_trylock()) {
/* Restore the original values before restarting */
*valp = val;
*ppos = pos;
return restart_syscall();
}
if (valp == &IPV4_DEVCONF_ALL(net, FORWARDING)) {
inet_forward_change(net);
} else if (*valp) {
Expand Down
16 changes: 14 additions & 2 deletions net/ipv6/addrconf.c
Expand Up @@ -502,8 +502,11 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
if (p == &net->ipv6.devconf_dflt->forwarding)
return 0;

if (!rtnl_trylock())
if (!rtnl_trylock()) {
/* Restore the original values before restarting */
*p = old;
return restart_syscall();
}

if (p == &net->ipv6.devconf_all->forwarding) {
__s32 newf = net->ipv6.devconf_all->forwarding;
Expand Down Expand Up @@ -4028,12 +4031,15 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write,
{
int *valp = ctl->data;
int val = *valp;
loff_t pos = *ppos;
int ret;

ret = proc_dointvec(ctl, write, buffer, lenp, ppos);

if (write)
ret = addrconf_fixup_forwarding(ctl, valp, val);
if (ret)
*ppos = pos;
return ret;
}

Expand Down Expand Up @@ -4075,8 +4081,11 @@ static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old)
if (p == &net->ipv6.devconf_dflt->disable_ipv6)
return 0;

if (!rtnl_trylock())
if (!rtnl_trylock()) {
/* Restore the original values before restarting */
*p = old;
return restart_syscall();
}

if (p == &net->ipv6.devconf_all->disable_ipv6) {
__s32 newf = net->ipv6.devconf_all->disable_ipv6;
Expand All @@ -4095,12 +4104,15 @@ int addrconf_sysctl_disable(ctl_table *ctl, int write,
{
int *valp = ctl->data;
int val = *valp;
loff_t pos = *ppos;
int ret;

ret = proc_dointvec(ctl, write, buffer, lenp, ppos);

if (write)
ret = addrconf_disable_ipv6(ctl, valp, val);
if (ret)
*ppos = pos;
return ret;
}

Expand Down

0 comments on commit 88af182

Please sign in to comment.