lkml.org 
[lkml]   [2010]   [Mar]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[039/145] net: Fix sysctl restarts...
2.6.32-stable review patch.  If anyone has any objections, please let me know.

----------------
From: Eric W. Biederman <ebiederm@xmission.com>

[ Upstream commit 88af182e389097997c5e2a0b42285b3522796759 ]

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>


---
net/ipv4/devinet.c | 7 ++++++-
net/ipv6/addrconf.c | 16 ++++++++++++++--
2 files changed, 20 insertions(+), 3 deletions(-)

--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1351,14 +1351,19 @@ static int devinet_sysctl_forward(ctl_ta
{
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) {
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -504,8 +504,11 @@ static int addrconf_fixup_forwarding(str
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;
@@ -3991,12 +3994,15 @@ int addrconf_sysctl_forward(ctl_table *c
{
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;
}

@@ -4075,8 +4081,11 @@ static int addrconf_disable_ipv6(struct
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;
@@ -4095,12 +4104,15 @@ int addrconf_sysctl_disable(ctl_table *c
{
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;
}




\
 
 \ /
  Last update: 2010-03-13 01:47    [W:0.387 / U:1.380 seconds]
©2003-2018 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site