diff options
Diffstat (limited to 'net/ipv6/ip6_output.c')
| -rw-r--r-- | net/ipv6/ip6_output.c | 13 | 
1 files changed, 11 insertions, 2 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 32e5339db0c..4c882cf4e8a 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -135,10 +135,15 @@ static int ip6_finish_output2(struct sk_buff *skb)  				skb->len);  	} +	rcu_read_lock();  	neigh = dst_get_neighbour(dst); -	if (neigh) -		return neigh_output(neigh, skb); +	if (neigh) { +		int res = neigh_output(neigh, skb); +		rcu_read_unlock(); +		return res; +	} +	rcu_read_unlock();  	IP6_INC_STATS_BH(dev_net(dst->dev),  			 ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);  	kfree_skb(skb); @@ -975,12 +980,14 @@ static int ip6_dst_lookup_tail(struct sock *sk,  	 * dst entry and replace it instead with the  	 * dst entry of the nexthop router  	 */ +	rcu_read_lock();  	n = dst_get_neighbour(*dst);  	if (n && !(n->nud_state & NUD_VALID)) {  		struct inet6_ifaddr *ifp;  		struct flowi6 fl_gw6;  		int redirect; +		rcu_read_unlock();  		ifp = ipv6_get_ifaddr(net, &fl6->saddr,  				      (*dst)->dev, 1); @@ -1000,6 +1007,8 @@ static int ip6_dst_lookup_tail(struct sock *sk,  			if ((err = (*dst)->error))  				goto out_err_release;  		} +	} else { +		rcu_read_unlock();  	}  #endif  |