diff options
Diffstat (limited to 'net/ipv6/inet6_connection_sock.c')
| -rw-r--r-- | net/ipv6/inet6_connection_sock.c | 21 | 
1 files changed, 9 insertions, 12 deletions
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 5d1c7cee2cb2..a7ca2cde2ecb 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c @@ -78,7 +78,9 @@ struct dst_entry *inet6_csk_route_req(const struct sock *sk,  	memset(fl6, 0, sizeof(*fl6));  	fl6->flowi6_proto = proto;  	fl6->daddr = ireq->ir_v6_rmt_addr; -	final_p = fl6_update_dst(fl6, np->opt, &final); +	rcu_read_lock(); +	final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final); +	rcu_read_unlock();  	fl6->saddr = ireq->ir_v6_loc_addr;  	fl6->flowi6_oif = ireq->ir_iif;  	fl6->flowi6_mark = ireq->ir_mark; @@ -109,14 +111,6 @@ void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr)  EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr);  static inline -void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst, -			   const struct in6_addr *daddr, -			   const struct in6_addr *saddr) -{ -	__ip6_dst_store(sk, dst, daddr, saddr); -} - -static inline  struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie)  {  	return __sk_dst_check(sk, cookie); @@ -142,14 +136,16 @@ static struct dst_entry *inet6_csk_route_socket(struct sock *sk,  	fl6->fl6_dport = inet->inet_dport;  	security_sk_classify_flow(sk, flowi6_to_flowi(fl6)); -	final_p = fl6_update_dst(fl6, np->opt, &final); +	rcu_read_lock(); +	final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final); +	rcu_read_unlock();  	dst = __inet6_csk_dst_check(sk, np->dst_cookie);  	if (!dst) {  		dst = ip6_dst_lookup_flow(sk, fl6, final_p);  		if (!IS_ERR(dst)) -			__inet6_csk_dst_store(sk, dst, NULL, NULL); +			ip6_dst_store(sk, dst, NULL, NULL);  	}  	return dst;  } @@ -175,7 +171,8 @@ int inet6_csk_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl_unused  	/* Restore final destination back after routing done */  	fl6.daddr = sk->sk_v6_daddr; -	res = ip6_xmit(sk, skb, &fl6, np->opt, np->tclass); +	res = ip6_xmit(sk, skb, &fl6, rcu_dereference(np->opt), +		       np->tclass);  	rcu_read_unlock();  	return res;  }  | 
