Message ID | 20190127072622.24835-1-nird@mellanox.com |
---|---|
State | Accepted |
Delegated to: | David Miller |
Headers | show |
Series | [net] ip6mr: Fix notifiers call on mroute_clean_tables() | expand |
From: Nir Dotan <nird@mellanox.com> Date: Sun, 27 Jan 2019 09:26:22 +0200 > When the MC route socket is closed, mroute_clean_tables() is called to > cleanup existing routes. Mistakenly notifiers call was put on the cleanup > of the unresolved MC route entries cache. > In a case where the MC socket closes before an unresolved route expires, > the notifier call leads to a crash, caused by the driver trying to > increment a non initialized refcount_t object [1] and then when handling > is done, to decrement it [2]. This was detected by a test recently added in > commit 6d4efada3b82 ("selftests: forwarding: Add multicast routing test"). > > Fix that by putting notifiers call on the resolved entries traversal, > instead of on the unresolved entries traversal. ... > Fixes: 088aa3eec2ce ("ip6mr: Support fib notifications") > Signed-off-by: Nir Dotan <nird@mellanox.com> > Reviewed-by: Ido Schimmel <idosch@mellanox.com> Applied and queued up for -stable, thanks.
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 30337b3..cc01aa3 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -1516,6 +1516,9 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all) continue; rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params); list_del_rcu(&c->list); + call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net), + FIB_EVENT_ENTRY_DEL, + (struct mfc6_cache *)c, mrt->id); mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE); mr_cache_put(c); } @@ -1524,10 +1527,6 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all) spin_lock_bh(&mfc_unres_lock); list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) { list_del(&c->list); - call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net), - FIB_EVENT_ENTRY_DEL, - (struct mfc6_cache *)c, - mrt->id); mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE); ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);