diff mbox series

[net,1/2] net: ipv6: fib: flush exceptions when purging route

Message ID 1609892546-11389-1-git-send-email-stranche@quicinc.com (mailing list archive)
State Accepted
Delegated to: Netdev Maintainers
Headers show
Series [net,1/2] net: ipv6: fib: flush exceptions when purging route | expand

Checks

Context Check Description
netdev/cover_letter success Link
netdev/fixes_present fail Series targets non-next tree, but doesn't contain any Fixes tags
netdev/patch_count success Link
netdev/tree_selection success Clearly marked for net
netdev/subject_prefix success Link
netdev/cc_maintainers warning 2 maintainers not CCed: kuznet@ms2.inr.ac.ru yoshfuji@linux-ipv6.org
netdev/source_inline success Was 0 now: 0
netdev/verify_signedoff success Link
netdev/module_param success Was 0 now: 0
netdev/build_32bit success Errors and warnings before: 1 this patch: 1
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/verify_fixes success Link
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 17 lines checked
netdev/build_allmodconfig_warn success Errors and warnings before: 1 this patch: 1
netdev/header_inline success Link
netdev/stable success Stable not CCed

Commit Message

Sean Tranchetti Jan. 6, 2021, 12:22 a.m. UTC
From: Sean Tranchetti <stranche@codeaurora.org>

Route removal is handled by two code paths. The main removal path is via
fib6_del_route() which will handle purging any PMTU exceptions from the
cache, removing all per-cpu copies of the DST entry used by the route, and
releasing the fib6_info struct.

The second removal location is during fib6_add_rt2node() during a route
replacement operation. This path also calls fib6_purge_rt() to handle
cleaning up the per-cpu copies of the DST entries and releasing the
fib6_info associated with the older route, but it does not flush any PMTU
exceptions that the older route had. Since the older route is removed from
the tree during the replacement, we lose any way of accessing it again.

As these lingering DSTs and the fib6_info struct are holding references to
the underlying netdevice struct as well, unregistering that device from the
kernel can never complete.

Signed-off-by: Sean Tranchetti <stranche@codeaurora.org>
---
 net/ipv6/ip6_fib.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

Comments

David Ahern Jan. 6, 2021, 4:55 p.m. UTC | #1
On 1/5/21 5:22 PM, Sean Tranchetti wrote:
> From: Sean Tranchetti <stranche@codeaurora.org>
> 
> Route removal is handled by two code paths. The main removal path is via
> fib6_del_route() which will handle purging any PMTU exceptions from the
> cache, removing all per-cpu copies of the DST entry used by the route, and
> releasing the fib6_info struct.
> 
> The second removal location is during fib6_add_rt2node() during a route
> replacement operation. This path also calls fib6_purge_rt() to handle
> cleaning up the per-cpu copies of the DST entries and releasing the
> fib6_info associated with the older route, but it does not flush any PMTU
> exceptions that the older route had. Since the older route is removed from
> the tree during the replacement, we lose any way of accessing it again.
> 
> As these lingering DSTs and the fib6_info struct are holding references to
> the underlying netdevice struct as well, unregistering that device from the
> kernel can never complete.
> 

I think the right fixes tag is:

Fixes: 2b760fcf5cfb3 ("ipv6: hook up exception table to store dst cache")

cc'ed author of that patch.

> Signed-off-by: Sean Tranchetti <stranche@codeaurora.org>
> ---
>  net/ipv6/ip6_fib.c | 5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
> 
> diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
> index 605cdd3..f43e275 100644
> --- a/net/ipv6/ip6_fib.c
> +++ b/net/ipv6/ip6_fib.c
> @@ -1025,6 +1025,8 @@ static void fib6_purge_rt(struct fib6_info *rt, struct fib6_node *fn,
>  {
>  	struct fib6_table *table = rt->fib6_table;
>  
> +	/* Flush all cached dst in exception table */
> +	rt6_flush_exceptions(rt);
>  	fib6_drop_pcpu_from(rt, table);
>  
>  	if (rt->nh && !list_empty(&rt->nh_list))
> @@ -1927,9 +1929,6 @@ static void fib6_del_route(struct fib6_table *table, struct fib6_node *fn,
>  	net->ipv6.rt6_stats->fib_rt_entries--;
>  	net->ipv6.rt6_stats->fib_discarded_routes++;
>  
> -	/* Flush all cached dst in exception table */
> -	rt6_flush_exceptions(rt);
> -
>  	/* Reset round-robin state, if necessary */
>  	if (rcu_access_pointer(fn->rr_ptr) == rt)
>  		fn->rr_ptr = NULL;
> 

Reviewed-by: David Ahern <dsahern@kernel.org>
Jakub Kicinski Jan. 7, 2021, 8:04 p.m. UTC | #2
On Wed, 6 Jan 2021 09:55:09 -0700 David Ahern wrote:
> On 1/5/21 5:22 PM, Sean Tranchetti wrote:
> > From: Sean Tranchetti <stranche@codeaurora.org>
> > 
> > Route removal is handled by two code paths. The main removal path is via
> > fib6_del_route() which will handle purging any PMTU exceptions from the
> > cache, removing all per-cpu copies of the DST entry used by the route, and
> > releasing the fib6_info struct.
> > 
> > The second removal location is during fib6_add_rt2node() during a route
> > replacement operation. This path also calls fib6_purge_rt() to handle
> > cleaning up the per-cpu copies of the DST entries and releasing the
> > fib6_info associated with the older route, but it does not flush any PMTU
> > exceptions that the older route had. Since the older route is removed from
> > the tree during the replacement, we lose any way of accessing it again.
> > 
> > As these lingering DSTs and the fib6_info struct are holding references to
> > the underlying netdevice struct as well, unregistering that device from the
> > kernel can never complete.
> 
> I think the right fixes tag is:
> 
> Fixes: 2b760fcf5cfb3 ("ipv6: hook up exception table to store dst cache")
> 
> cc'ed author of that patch.
> 
> > Signed-off-by: Sean Tranchetti <stranche@codeaurora.org>
>
> Reviewed-by: David Ahern <dsahern@kernel.org>

Applied, thanks!
diff mbox series

Patch

diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 605cdd3..f43e275 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -1025,6 +1025,8 @@  static void fib6_purge_rt(struct fib6_info *rt, struct fib6_node *fn,
 {
 	struct fib6_table *table = rt->fib6_table;
 
+	/* Flush all cached dst in exception table */
+	rt6_flush_exceptions(rt);
 	fib6_drop_pcpu_from(rt, table);
 
 	if (rt->nh && !list_empty(&rt->nh_list))
@@ -1927,9 +1929,6 @@  static void fib6_del_route(struct fib6_table *table, struct fib6_node *fn,
 	net->ipv6.rt6_stats->fib_rt_entries--;
 	net->ipv6.rt6_stats->fib_discarded_routes++;
 
-	/* Flush all cached dst in exception table */
-	rt6_flush_exceptions(rt);
-
 	/* Reset round-robin state, if necessary */
 	if (rcu_access_pointer(fn->rr_ptr) == rt)
 		fn->rr_ptr = NULL;