diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index a9ed2ccab1bdb0682dcd029d252d0ac6563818d0..a2da1f3f4cd2483aab83e02ca89a11ab07c14b50 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -81,6 +81,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev, struct net *net = dev_net(ifa->idev->dev); int found = 0; + ASSERT_RTNL(); switch (ev) { case NETDEV_UP: addr = kzalloc(sizeof(*addr), GFP_ATOMIC); diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 8b9a1b96695e08aa1f0dfc0c7c4d48ebbf5df82e..6bb4a5ab1554d91b33b191a35b77aa76985b0c0e 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -116,17 +116,21 @@ static void sctp_get_local_addr_list(struct net *net) rcu_read_unlock(); } -/* Free the existing local addresses. */ +/* Free the existing local addresses. + * RTNL is not held. + */ static void sctp_free_local_addr_list(struct net *net) { struct sctp_sockaddr_entry *addr; struct list_head *pos, *temp; + spin_lock_bh(&net->sctp.local_addr_lock); list_for_each_safe(pos, temp, &net->sctp.local_addr_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - list_del(pos); - kfree(addr); + list_del_rcu(pos); + kfree_rcu(addr, rcu); } + spin_unlock_bh(&net->sctp.local_addr_lock); } /* Copy the local addresses which are valid for 'scope' into 'bp'. */ @@ -802,6 +806,7 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, struct net *net = dev_net(ifa->ifa_dev->dev); int found = 0; + ASSERT_RTNL(); switch (ev) { case NETDEV_UP: addr = kzalloc(sizeof(*addr), GFP_ATOMIC);