mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	ipv6: Don't create clones of host routes.
Addresses https://bugzilla.kernel.org/show_bug.cgi?id=29252
Addresses https://bugzilla.kernel.org/show_bug.cgi?id=30462
In commit d80bc0fd26 ("ipv6: Always
clone offlink routes.") we forced the kernel to always clone offlink
routes.
The reason we do that is to make sure we never bind an inetpeer to a
prefixed route.
The logic turned on here has existed in the tree for many years,
but was always off due to a protecting CPP define.  So perhaps
it's no surprise that there is a logic bug here.
The problem is that we canot clone a route that is already a
host route (ie. has DST_HOST set).  Because if we do, an identical
entry already exists in the routing tree and therefore the
ip6_rt_ins() call is going to fail.
This sets off a series of failures and high cpu usage, because when
ip6_rt_ins() fails we loop retrying this operation a few times in
order to handle a race between two threads trying to clone and insert
the same host route at the same time.
Fix this by simply using the route as-is when DST_HOST is set.
Reported-by: slash@ac.auone-net.jp
Reported-by: Ernst Sjöstrand <ernstp@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									03a14ab134
								
							
						
					
					
						commit
						7343ff31eb
					
				
					 1 changed files with 3 additions and 1 deletions
				
			
		| 
						 | 
					@ -739,8 +739,10 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
 | 
						if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
 | 
				
			||||||
		nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src);
 | 
							nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src);
 | 
				
			||||||
	else
 | 
						else if (!(rt->dst.flags & DST_HOST))
 | 
				
			||||||
		nrt = rt6_alloc_clone(rt, &fl->fl6_dst);
 | 
							nrt = rt6_alloc_clone(rt, &fl->fl6_dst);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							goto out2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dst_release(&rt->dst);
 | 
						dst_release(&rt->dst);
 | 
				
			||||||
	rt = nrt ? : net->ipv6.ip6_null_entry;
 | 
						rt = nrt ? : net->ipv6.ip6_null_entry;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue