|
@@ -1278,7 +1278,7 @@ static void mrtsock_destruct(struct sock *sk)
|
|
struct net *net = sock_net(sk);
|
|
struct net *net = sock_net(sk);
|
|
struct mr_table *mrt;
|
|
struct mr_table *mrt;
|
|
|
|
|
|
- rtnl_lock();
|
|
|
|
|
|
+ ASSERT_RTNL();
|
|
ipmr_for_each_table(mrt, net) {
|
|
ipmr_for_each_table(mrt, net) {
|
|
if (sk == rtnl_dereference(mrt->mroute_sk)) {
|
|
if (sk == rtnl_dereference(mrt->mroute_sk)) {
|
|
IPV4_DEVCONF_ALL(net, MC_FORWARDING)--;
|
|
IPV4_DEVCONF_ALL(net, MC_FORWARDING)--;
|
|
@@ -1289,7 +1289,6 @@ static void mrtsock_destruct(struct sock *sk)
|
|
mroute_clean_tables(mrt, false);
|
|
mroute_clean_tables(mrt, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- rtnl_unlock();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/* Socket options and virtual interface manipulation. The whole
|
|
/* Socket options and virtual interface manipulation. The whole
|
|
@@ -1353,13 +1352,8 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval,
|
|
if (sk != rcu_access_pointer(mrt->mroute_sk)) {
|
|
if (sk != rcu_access_pointer(mrt->mroute_sk)) {
|
|
ret = -EACCES;
|
|
ret = -EACCES;
|
|
} else {
|
|
} else {
|
|
- /* We need to unlock here because mrtsock_destruct takes
|
|
|
|
- * care of rtnl itself and we can't change that due to
|
|
|
|
- * the IP_ROUTER_ALERT setsockopt which runs without it.
|
|
|
|
- */
|
|
|
|
- rtnl_unlock();
|
|
|
|
ret = ip_ra_control(sk, 0, NULL);
|
|
ret = ip_ra_control(sk, 0, NULL);
|
|
- goto out;
|
|
|
|
|
|
+ goto out_unlock;
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
case MRT_ADD_VIF:
|
|
case MRT_ADD_VIF:
|
|
@@ -1470,7 +1464,6 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval,
|
|
}
|
|
}
|
|
out_unlock:
|
|
out_unlock:
|
|
rtnl_unlock();
|
|
rtnl_unlock();
|
|
-out:
|
|
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|