diff options
Diffstat (limited to 'net/ipv4/tcp_ao.c')
| -rw-r--r-- | net/ipv4/tcp_ao.c | 19 | 
1 files changed, 13 insertions, 6 deletions
diff --git a/net/ipv4/tcp_ao.c b/net/ipv4/tcp_ao.c index 781b67a52571..09c0fa6756b7 100644 --- a/net/ipv4/tcp_ao.c +++ b/net/ipv4/tcp_ao.c @@ -933,6 +933,7 @@ tcp_inbound_ao_hash(struct sock *sk, const struct sk_buff *skb,  	struct tcp_ao_key *key;  	__be32 sisn, disn;  	u8 *traffic_key; +	int state;  	u32 sne = 0;  	info = rcu_dereference(tcp_sk(sk)->ao_info); @@ -948,8 +949,9 @@ tcp_inbound_ao_hash(struct sock *sk, const struct sk_buff *skb,  		disn = 0;  	} +	state = READ_ONCE(sk->sk_state);  	/* Fast-path */ -	if (likely((1 << sk->sk_state) & TCP_AO_ESTABLISHED)) { +	if (likely((1 << state) & TCP_AO_ESTABLISHED)) {  		enum skb_drop_reason err;  		struct tcp_ao_key *current_key; @@ -988,6 +990,9 @@ tcp_inbound_ao_hash(struct sock *sk, const struct sk_buff *skb,  		return SKB_NOT_DROPPED_YET;  	} +	if (unlikely(state == TCP_CLOSE)) +		return SKB_DROP_REASON_TCP_CLOSE; +  	/* Lookup key based on peer address and keyid.  	 * current_key and rnext_key must not be used on tcp listen  	 * sockets as otherwise: @@ -1001,7 +1006,7 @@ tcp_inbound_ao_hash(struct sock *sk, const struct sk_buff *skb,  	if (th->syn && !th->ack)  		goto verify_hash; -	if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_NEW_SYN_RECV)) { +	if ((1 << state) & (TCPF_LISTEN | TCPF_NEW_SYN_RECV)) {  		/* Make the initial syn the likely case here */  		if (unlikely(req)) {  			sne = tcp_ao_compute_sne(0, tcp_rsk(req)->rcv_isn, @@ -1018,14 +1023,14 @@ tcp_inbound_ao_hash(struct sock *sk, const struct sk_buff *skb,  			/* no way to figure out initial sisn/disn - drop */  			return SKB_DROP_REASON_TCP_FLAGS;  		} -	} else if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { +	} else if ((1 << state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {  		disn = info->lisn;  		if (th->syn || th->rst)  			sisn = th->seq;  		else  			sisn = info->risn;  	} else { -		WARN_ONCE(1, "TCP-AO: Unexpected sk_state %d", sk->sk_state); +		WARN_ONCE(1, "TCP-AO: Unexpected sk_state %d", state);  		return SKB_DROP_REASON_TCP_AOFAILURE;  	}  verify_hash: @@ -1963,8 +1968,10 @@ static int tcp_ao_info_cmd(struct sock *sk, unsigned short int family,  		first = true;  	} -	if (cmd.ao_required && tcp_ao_required_verify(sk)) -		return -EKEYREJECTED; +	if (cmd.ao_required && tcp_ao_required_verify(sk)) { +		err = -EKEYREJECTED; +		goto out; +	}  	/* For sockets in TCP_CLOSED it's possible set keys that aren't  	 * matching the future peer (address/port/VRF/etc),  | 
