Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net/tcp: Sign SYN-ACK segments with TCP-AO

Similarly to RST segments, wire SYN-ACKs to TCP-AO.
tcp_rsk_used_ao() is handy here to check if the request socket used AO
and needs a signature on the outgoing segments.

Co-developed-by: Francesco Ruggeri <fruggeri@arista.com>
Signed-off-by: Francesco Ruggeri <fruggeri@arista.com>
Co-developed-by: Salam Noureddine <noureddine@arista.com>
Signed-off-by: Salam Noureddine <noureddine@arista.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Acked-by: David Ahern <dsahern@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Dmitry Safonov and committed by
David S. Miller
9427c6aa 06b22ef2

+111 -16
+3
include/net/tcp.h
··· 2221 2221 struct request_sock *req, 2222 2222 int sndid, int rcvid); 2223 2223 int (*ao_calc_key)(struct tcp_ao_key *mkt, u8 *key, struct request_sock *sk); 2224 + int (*ao_synack_hash)(char *ao_hash, struct tcp_ao_key *mkt, 2225 + struct request_sock *req, const struct sk_buff *skb, 2226 + int hash_offset, u32 sne); 2224 2227 #endif 2225 2228 #ifdef CONFIG_SYN_COOKIES 2226 2229 __u32 (*cookie_init_seq)(const struct sk_buff *skb,
+6
include/net/tcp_ao.h
··· 147 147 int tcp_v4_parse_ao(struct sock *sk, int cmd, sockptr_t optval, int optlen); 148 148 struct tcp_ao_key *tcp_v4_ao_lookup(const struct sock *sk, struct sock *addr_sk, 149 149 int sndid, int rcvid); 150 + int tcp_v4_ao_synack_hash(char *ao_hash, struct tcp_ao_key *mkt, 151 + struct request_sock *req, const struct sk_buff *skb, 152 + int hash_offset, u32 sne); 150 153 int tcp_v4_ao_calc_key_sk(struct tcp_ao_key *mkt, u8 *key, 151 154 const struct sock *sk, 152 155 __be32 sisn, __be32 disn, bool send); ··· 184 181 const struct sock *sk, const struct sk_buff *skb, 185 182 const u8 *tkey, int hash_offset, u32 sne); 186 183 int tcp_v6_parse_ao(struct sock *sk, int cmd, sockptr_t optval, int optlen); 184 + int tcp_v6_ao_synack_hash(char *ao_hash, struct tcp_ao_key *ao_key, 185 + struct request_sock *req, const struct sk_buff *skb, 186 + int hash_offset, u32 sne); 187 187 void tcp_ao_established(struct sock *sk); 188 188 void tcp_ao_finish_connect(struct sock *sk, struct sk_buff *skb); 189 189 void tcp_ao_connect_init(struct sock *sk);
+22
net/ipv4/tcp_ao.c
··· 568 568 tkey, hash_offset, sne); 569 569 } 570 570 571 + int tcp_v4_ao_synack_hash(char *ao_hash, struct tcp_ao_key *ao_key, 572 + struct request_sock *req, const struct sk_buff *skb, 573 + int hash_offset, u32 sne) 574 + { 575 + void *hash_buf = NULL; 576 + int err; 577 + 578 + hash_buf = kmalloc(tcp_ao_digest_size(ao_key), GFP_ATOMIC); 579 + if (!hash_buf) 580 + return -ENOMEM; 581 + 582 + err = tcp_v4_ao_calc_key_rsk(ao_key, hash_buf, req); 583 + if (err) 584 + goto out; 585 + 586 + err = tcp_ao_hash_skb(AF_INET, ao_hash, ao_key, req_to_sk(req), skb, 587 + hash_buf, hash_offset, sne); 588 + out: 589 + kfree(hash_buf); 590 + return err; 591 + } 592 + 571 593 struct tcp_ao_key *tcp_v4_ao_lookup_rsk(const struct sock *sk, 572 594 struct request_sock *req, 573 595 int sndid, int rcvid)
+1
net/ipv4/tcp_ipv4.c
··· 1681 1681 #ifdef CONFIG_TCP_AO 1682 1682 .ao_lookup = tcp_v4_ao_lookup_rsk, 1683 1683 .ao_calc_key = tcp_v4_ao_calc_key_rsk, 1684 + .ao_synack_hash = tcp_v4_ao_synack_hash, 1684 1685 #endif 1685 1686 #ifdef CONFIG_SYN_COOKIES 1686 1687 .cookie_init_seq = cookie_v4_init_sequence,
+56 -16
net/ipv4/tcp_output.c
··· 886 886 struct request_sock *req, 887 887 unsigned int mss, struct sk_buff *skb, 888 888 struct tcp_out_options *opts, 889 - const struct tcp_md5sig_key *md5, 889 + const struct tcp_key *key, 890 890 struct tcp_fastopen_cookie *foc, 891 891 enum tcp_synack_type synack_type, 892 892 struct sk_buff *syn_skb) ··· 894 894 struct inet_request_sock *ireq = inet_rsk(req); 895 895 unsigned int remaining = MAX_TCP_OPTION_SPACE; 896 896 897 - #ifdef CONFIG_TCP_MD5SIG 898 - if (md5) { 897 + if (tcp_key_is_md5(key)) { 899 898 opts->options |= OPTION_MD5; 900 899 remaining -= TCPOLEN_MD5SIG_ALIGNED; 901 900 ··· 905 906 */ 906 907 if (synack_type != TCP_SYNACK_COOKIE) 907 908 ireq->tstamp_ok &= !ireq->sack_ok; 909 + } else if (tcp_key_is_ao(key)) { 910 + opts->options |= OPTION_AO; 911 + remaining -= tcp_ao_len(key->ao_key); 912 + ireq->tstamp_ok &= !ireq->sack_ok; 908 913 } 909 - #endif 910 914 911 915 /* We always send an MSS option. */ 912 916 opts->mss = mss; ··· 3655 3653 { 3656 3654 struct inet_request_sock *ireq = inet_rsk(req); 3657 3655 const struct tcp_sock *tp = tcp_sk(sk); 3658 - struct tcp_md5sig_key *md5 = NULL; 3659 3656 struct tcp_out_options opts; 3660 3657 struct tcp_key key = {}; 3661 3658 struct sk_buff *skb; ··· 3708 3707 tcp_rsk(req)->snt_synack = tcp_skb_timestamp_us(skb); 3709 3708 } 3710 3709 3711 - #ifdef CONFIG_TCP_MD5SIG 3710 + #if defined(CONFIG_TCP_MD5SIG) || defined(CONFIG_TCP_AO) 3712 3711 rcu_read_lock(); 3713 - md5 = tcp_rsk(req)->af_specific->req_md5_lookup(sk, req_to_sk(req)); 3714 - if (md5) 3715 - key.type = TCP_KEY_MD5; 3716 3712 #endif 3713 + if (tcp_rsk_used_ao(req)) { 3714 + #ifdef CONFIG_TCP_AO 3715 + struct tcp_ao_key *ao_key = NULL; 3716 + u8 maclen = tcp_rsk(req)->maclen; 3717 + u8 keyid = tcp_rsk(req)->ao_keyid; 3718 + 3719 + ao_key = tcp_sk(sk)->af_specific->ao_lookup(sk, req_to_sk(req), 3720 + keyid, -1); 3721 + /* If there is no matching key - avoid sending anything, 3722 + * especially usigned segments. It could try harder and lookup 3723 + * for another peer-matching key, but the peer has requested 3724 + * ao_keyid (RFC5925 RNextKeyID), so let's keep it simple here. 3725 + */ 3726 + if (unlikely(!ao_key || tcp_ao_maclen(ao_key) != maclen)) { 3727 + u8 key_maclen = ao_key ? tcp_ao_maclen(ao_key) : 0; 3728 + 3729 + rcu_read_unlock(); 3730 + kfree_skb(skb); 3731 + net_warn_ratelimited("TCP-AO: the keyid %u with maclen %u|%u from SYN packet is not present - not sending SYNACK\n", 3732 + keyid, maclen, key_maclen); 3733 + return NULL; 3734 + } 3735 + key.ao_key = ao_key; 3736 + key.type = TCP_KEY_AO; 3737 + #endif 3738 + } else { 3739 + #ifdef CONFIG_TCP_MD5SIG 3740 + key.md5_key = tcp_rsk(req)->af_specific->req_md5_lookup(sk, 3741 + req_to_sk(req)); 3742 + if (key.md5_key) 3743 + key.type = TCP_KEY_MD5; 3744 + #endif 3745 + } 3717 3746 skb_set_hash(skb, READ_ONCE(tcp_rsk(req)->txhash), PKT_HASH_TYPE_L4); 3718 3747 /* bpf program will be interested in the tcp_flags */ 3719 3748 TCP_SKB_CB(skb)->tcp_flags = TCPHDR_SYN | TCPHDR_ACK; 3720 - tcp_header_size = tcp_synack_options(sk, req, mss, skb, &opts, md5, 3721 - foc, synack_type, 3722 - syn_skb) + sizeof(*th); 3749 + tcp_header_size = tcp_synack_options(sk, req, mss, skb, &opts, 3750 + &key, foc, synack_type, syn_skb) 3751 + + sizeof(*th); 3723 3752 3724 3753 skb_push(skb, tcp_header_size); 3725 3754 skb_reset_transport_header(skb); ··· 3769 3738 3770 3739 /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */ 3771 3740 th->window = htons(min(req->rsk_rcv_wnd, 65535U)); 3772 - tcp_options_write(th, NULL, NULL, &opts, &key); 3741 + tcp_options_write(th, NULL, tcp_rsk(req), &opts, &key); 3773 3742 th->doff = (tcp_header_size >> 2); 3774 3743 TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); 3775 3744 3776 - #ifdef CONFIG_TCP_MD5SIG 3777 3745 /* Okay, we have all we need - do the md5 hash if needed */ 3778 - if (md5) 3746 + if (tcp_key_is_md5(&key)) { 3747 + #ifdef CONFIG_TCP_MD5SIG 3779 3748 tcp_rsk(req)->af_specific->calc_md5_hash(opts.hash_location, 3780 - md5, req_to_sk(req), skb); 3749 + key.md5_key, req_to_sk(req), skb); 3750 + #endif 3751 + } else if (tcp_key_is_ao(&key)) { 3752 + #ifdef CONFIG_TCP_AO 3753 + tcp_rsk(req)->af_specific->ao_synack_hash(opts.hash_location, 3754 + key.ao_key, req, skb, 3755 + opts.hash_location - (u8 *)th, 0); 3756 + #endif 3757 + } 3758 + #if defined(CONFIG_TCP_MD5SIG) || defined(CONFIG_TCP_AO) 3781 3759 rcu_read_unlock(); 3782 3760 #endif 3783 3761
+22
net/ipv6/tcp_ao.c
··· 144 144 { 145 145 return tcp_parse_ao(sk, cmd, AF_INET6, optval, optlen); 146 146 } 147 + 148 + int tcp_v6_ao_synack_hash(char *ao_hash, struct tcp_ao_key *ao_key, 149 + struct request_sock *req, const struct sk_buff *skb, 150 + int hash_offset, u32 sne) 151 + { 152 + void *hash_buf = NULL; 153 + int err; 154 + 155 + hash_buf = kmalloc(tcp_ao_digest_size(ao_key), GFP_ATOMIC); 156 + if (!hash_buf) 157 + return -ENOMEM; 158 + 159 + err = tcp_v6_ao_calc_key_rsk(ao_key, hash_buf, req); 160 + if (err) 161 + goto out; 162 + 163 + err = tcp_ao_hash_skb(AF_INET6, ao_hash, ao_key, req_to_sk(req), skb, 164 + hash_buf, hash_offset, sne); 165 + out: 166 + kfree(hash_buf); 167 + return err; 168 + }
+1
net/ipv6/tcp_ipv6.c
··· 839 839 #ifdef CONFIG_TCP_AO 840 840 .ao_lookup = tcp_v6_ao_lookup_rsk, 841 841 .ao_calc_key = tcp_v6_ao_calc_key_rsk, 842 + .ao_synack_hash = tcp_v6_ao_synack_hash, 842 843 #endif 843 844 #ifdef CONFIG_SYN_COOKIES 844 845 .cookie_init_seq = cookie_v6_init_sequence,