Commit 8c171d6c authored by Felix Jia's avatar Felix Jia Committed by David S. Miller

net/ipv6: avoid possible dead locking on addr_gen_mode sysctl

The addr_gen_mode variable can be accessed by both sysctl and netlink.
Repleacd rtnl_lock() with rtnl_trylock() protect the sysctl operation to
avoid the possbile dead lock.`
Signed-off-by: default avatarFelix Jia <felix.jia@alliedtelesis.co.nz>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a3695e97
...@@ -5692,13 +5692,18 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write, ...@@ -5692,13 +5692,18 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
struct inet6_dev *idev = (struct inet6_dev *)ctl->extra1; struct inet6_dev *idev = (struct inet6_dev *)ctl->extra1;
struct net *net = (struct net *)ctl->extra2; struct net *net = (struct net *)ctl->extra2;
if (!rtnl_trylock())
return restart_syscall();
ret = proc_dointvec(ctl, write, buffer, lenp, ppos); ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
if (write) { if (write) {
new_val = *((int *)ctl->data); new_val = *((int *)ctl->data);
if (check_addr_gen_mode(new_val) < 0) if (check_addr_gen_mode(new_val) < 0) {
return -EINVAL; ret = -EINVAL;
goto out;
}
/* request for default */ /* request for default */
if (&net->ipv6.devconf_dflt->addr_gen_mode == ctl->data) { if (&net->ipv6.devconf_dflt->addr_gen_mode == ctl->data) {
...@@ -5707,20 +5712,23 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write, ...@@ -5707,20 +5712,23 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
/* request for individual net device */ /* request for individual net device */
} else { } else {
if (!idev) if (!idev)
return ret; goto out;
if (check_stable_privacy(idev, net, new_val) < 0) if (check_stable_privacy(idev, net, new_val) < 0) {
return -EINVAL; ret = -EINVAL;
goto out;
}
if (idev->cnf.addr_gen_mode != new_val) { if (idev->cnf.addr_gen_mode != new_val) {
idev->cnf.addr_gen_mode = new_val; idev->cnf.addr_gen_mode = new_val;
rtnl_lock();
addrconf_dev_config(idev->dev); addrconf_dev_config(idev->dev);
rtnl_unlock();
} }
} }
} }
out:
rtnl_unlock();
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment