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: Felix Jia <felix.jia@alliedtelesis.co.nz> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a3695e9751
commit
8c171d6ca5
@ -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,
|
|||||||
/* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user