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: Wire TCP-AO to request sockets

Now when the new request socket is created from the listening socket,
it's recorded what MKT was used by the peer. tcp_rsk_used_ao() is
a new helper for checking if TCP-AO option was used to create the
request socket.
tcp_ao_copy_all_matching() will copy all keys that match the peer on the
request socket, as well as preparing them for the usage (creating
traffic keys).

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
06b22ef2 decde258

+505 -50
+18
include/linux/tcp.h
··· 166 166 * after data-in-SYN. 167 167 */ 168 168 u8 syn_tos; 169 + #ifdef CONFIG_TCP_AO 170 + u8 ao_keyid; 171 + u8 ao_rcv_next; 172 + u8 maclen; 173 + #endif 169 174 }; 170 175 171 176 static inline struct tcp_request_sock *tcp_rsk(const struct request_sock *req) 172 177 { 173 178 return (struct tcp_request_sock *)req; 179 + } 180 + 181 + static inline bool tcp_rsk_used_ao(const struct request_sock *req) 182 + { 183 + /* The real length of MAC is saved in the request socket, 184 + * signing anything with zero-length makes no sense, so here is 185 + * a little hack.. 186 + */ 187 + #ifndef CONFIG_TCP_AO 188 + return false; 189 + #else 190 + return tcp_rsk(req)->maclen != 0; 191 + #endif 174 192 } 175 193 176 194 #define TCP_RMEM_TO_WIN_SCALE 8
+6
include/net/tcp.h
··· 2216 2216 const struct sock *sk, 2217 2217 const struct sk_buff *skb); 2218 2218 #endif 2219 + #ifdef CONFIG_TCP_AO 2220 + struct tcp_ao_key *(*ao_lookup)(const struct sock *sk, 2221 + struct request_sock *req, 2222 + int sndid, int rcvid); 2223 + int (*ao_calc_key)(struct tcp_ao_key *mkt, u8 *key, struct request_sock *sk); 2224 + #endif 2219 2225 #ifdef CONFIG_SYN_COOKIES 2220 2226 __u32 (*cookie_init_seq)(const struct sk_buff *skb, 2221 2227 __u16 *mss);
+24
include/net/tcp_ao.h
··· 123 123 sockptr_t optval, int optlen); 124 124 struct tcp_ao_key *tcp_ao_established_key(struct tcp_ao_info *ao, 125 125 int sndid, int rcvid); 126 + int tcp_ao_copy_all_matching(const struct sock *sk, struct sock *newsk, 127 + struct request_sock *req, struct sk_buff *skb, 128 + int family); 126 129 int tcp_ao_calc_traffic_key(struct tcp_ao_key *mkt, u8 *key, void *ctx, 127 130 unsigned int len, struct tcp_sigpool *hp); 128 131 void tcp_ao_destroy_sock(struct sock *sk, bool twsk); ··· 150 147 int tcp_v4_ao_calc_key_sk(struct tcp_ao_key *mkt, u8 *key, 151 148 const struct sock *sk, 152 149 __be32 sisn, __be32 disn, bool send); 150 + int tcp_v4_ao_calc_key_rsk(struct tcp_ao_key *mkt, u8 *key, 151 + struct request_sock *req); 152 + struct tcp_ao_key *tcp_v4_ao_lookup_rsk(const struct sock *sk, 153 + struct request_sock *req, 154 + int sndid, int rcvid); 153 155 int tcp_v4_ao_hash_skb(char *ao_hash, struct tcp_ao_key *key, 154 156 const struct sock *sk, const struct sk_buff *skb, 155 157 const u8 *tkey, int hash_offset, u32 sne); ··· 162 154 int tcp_v6_ao_hash_pseudoheader(struct tcp_sigpool *hp, 163 155 const struct in6_addr *daddr, 164 156 const struct in6_addr *saddr, int nbytes); 157 + int tcp_v6_ao_calc_key_skb(struct tcp_ao_key *mkt, u8 *key, 158 + const struct sk_buff *skb, __be32 sisn, __be32 disn); 165 159 int tcp_v6_ao_calc_key_sk(struct tcp_ao_key *mkt, u8 *key, 166 160 const struct sock *sk, __be32 sisn, 167 161 __be32 disn, bool send); 162 + int tcp_v6_ao_calc_key_rsk(struct tcp_ao_key *mkt, u8 *key, 163 + struct request_sock *req); 164 + struct tcp_ao_key *tcp_v6_ao_do_lookup(const struct sock *sk, 165 + const struct in6_addr *addr, 166 + int sndid, int rcvid); 168 167 struct tcp_ao_key *tcp_v6_ao_lookup(const struct sock *sk, 169 168 struct sock *addr_sk, int sndid, int rcvid); 169 + struct tcp_ao_key *tcp_v6_ao_lookup_rsk(const struct sock *sk, 170 + struct request_sock *req, 171 + int sndid, int rcvid); 170 172 int tcp_v6_ao_hash_skb(char *ao_hash, struct tcp_ao_key *key, 171 173 const struct sock *sk, const struct sk_buff *skb, 172 174 const u8 *tkey, int hash_offset, u32 sne); ··· 194 176 __u8 *hash_location) 195 177 { 196 178 return 0; 179 + } 180 + 181 + static inline void tcp_ao_syncookie(struct sock *sk, const struct sk_buff *skb, 182 + struct tcp_request_sock *treq, 183 + unsigned short int family) 184 + { 197 185 } 198 186 199 187 static inline struct tcp_ao_key *tcp_ao_do_lookup(const struct sock *sk,
+2
net/ipv4/syncookies.c
··· 400 400 treq->snt_synack = 0; 401 401 treq->tfo_listener = false; 402 402 403 + tcp_ao_syncookie(sk, skb, treq, AF_INET); 404 + 403 405 if (IS_ENABLED(CONFIG_SMC)) 404 406 ireq->smc_ok = 0; 405 407
+250 -14
net/ipv4/tcp_ao.c
··· 169 169 hlist_add_head_rcu(&mkt->node, &ao->head); 170 170 } 171 171 172 + static struct tcp_ao_key *tcp_ao_copy_key(struct sock *sk, 173 + struct tcp_ao_key *key) 174 + { 175 + struct tcp_ao_key *new_key; 176 + 177 + new_key = sock_kmalloc(sk, tcp_ao_sizeof_key(key), 178 + GFP_ATOMIC); 179 + if (!new_key) 180 + return NULL; 181 + 182 + *new_key = *key; 183 + INIT_HLIST_NODE(&new_key->node); 184 + tcp_sigpool_get(new_key->tcp_sigpool_id); 185 + 186 + return new_key; 187 + } 188 + 172 189 static void tcp_ao_key_free_rcu(struct rcu_head *head) 173 190 { 174 191 struct tcp_ao_key *key = container_of(head, struct tcp_ao_key, rcu); ··· 305 288 #endif 306 289 else 307 290 return -EOPNOTSUPP; 291 + } 292 + 293 + int tcp_v4_ao_calc_key_rsk(struct tcp_ao_key *mkt, u8 *key, 294 + struct request_sock *req) 295 + { 296 + struct inet_request_sock *ireq = inet_rsk(req); 297 + 298 + return tcp_v4_ao_calc_key(mkt, key, 299 + ireq->ir_loc_addr, ireq->ir_rmt_addr, 300 + htons(ireq->ir_num), ireq->ir_rmt_port, 301 + htonl(tcp_rsk(req)->snt_isn), 302 + htonl(tcp_rsk(req)->rcv_isn)); 303 + } 304 + 305 + static int tcp_v4_ao_calc_key_skb(struct tcp_ao_key *mkt, u8 *key, 306 + const struct sk_buff *skb, 307 + __be32 sisn, __be32 disn) 308 + { 309 + const struct iphdr *iph = ip_hdr(skb); 310 + const struct tcphdr *th = tcp_hdr(skb); 311 + 312 + return tcp_v4_ao_calc_key(mkt, key, iph->saddr, iph->daddr, 313 + th->source, th->dest, sisn, disn); 314 + } 315 + 316 + static int tcp_ao_calc_key_skb(struct tcp_ao_key *mkt, u8 *key, 317 + const struct sk_buff *skb, 318 + __be32 sisn, __be32 disn, int family) 319 + { 320 + if (family == AF_INET) 321 + return tcp_v4_ao_calc_key_skb(mkt, key, skb, sisn, disn); 322 + #if IS_ENABLED(CONFIG_IPV6) 323 + else if (family == AF_INET6) 324 + return tcp_v6_ao_calc_key_skb(mkt, key, skb, sisn, disn); 325 + #endif 326 + return -EAFNOSUPPORT; 308 327 } 309 328 310 329 static int tcp_v4_ao_hash_pseudoheader(struct tcp_sigpool *hp, ··· 568 515 tkey, hash_offset, sne); 569 516 } 570 517 518 + struct tcp_ao_key *tcp_v4_ao_lookup_rsk(const struct sock *sk, 519 + struct request_sock *req, 520 + int sndid, int rcvid) 521 + { 522 + union tcp_ao_addr *addr = 523 + (union tcp_ao_addr *)&inet_rsk(req)->ir_rmt_addr; 524 + 525 + return tcp_ao_do_lookup(sk, addr, AF_INET, sndid, rcvid); 526 + } 527 + 571 528 struct tcp_ao_key *tcp_v4_ao_lookup(const struct sock *sk, struct sock *addr_sk, 572 529 int sndid, int rcvid) 573 530 { ··· 591 528 struct tcp_ao_key **key, char **traffic_key, 592 529 bool *allocated_traffic_key, u8 *keyid, u32 *sne) 593 530 { 594 - struct tcp_ao_key *rnext_key; 531 + const struct tcphdr *th = tcp_hdr(skb); 595 532 struct tcp_ao_info *ao_info; 596 533 597 534 *allocated_traffic_key = false; ··· 606 543 return -ENOTCONN; 607 544 608 545 if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_NEW_SYN_RECV)) { 609 - return -1; 546 + unsigned int family = READ_ONCE(sk->sk_family); 547 + union tcp_ao_addr *addr; 548 + __be32 disn, sisn; 610 549 611 - if (sk->sk_state == TCP_TIME_WAIT) 612 - ao_info = rcu_dereference(tcp_twsk(sk)->ao_info); 613 - else 550 + if (sk->sk_state == TCP_NEW_SYN_RECV) { 551 + struct request_sock *req = inet_reqsk(sk); 552 + 553 + sisn = htonl(tcp_rsk(req)->rcv_isn); 554 + disn = htonl(tcp_rsk(req)->snt_isn); 555 + *sne = 0; 556 + } else { 557 + sisn = th->seq; 558 + disn = 0; 559 + } 560 + if (IS_ENABLED(CONFIG_IPV6) && family == AF_INET6) 561 + addr = (union tcp_md5_addr *)&ipv6_hdr(skb)->saddr; 562 + else 563 + addr = (union tcp_md5_addr *)&ip_hdr(skb)->saddr; 564 + #if IS_ENABLED(CONFIG_IPV6) 565 + if (family == AF_INET6 && ipv6_addr_v4mapped(&sk->sk_v6_daddr)) 566 + family = AF_INET; 567 + #endif 568 + 569 + sk = sk_const_to_full_sk(sk); 614 570 ao_info = rcu_dereference(tcp_sk(sk)->ao_info); 615 - if (!ao_info) 616 - return -ENOENT; 571 + if (!ao_info) 572 + return -ENOENT; 573 + *key = tcp_ao_do_lookup(sk, addr, family, -1, aoh->rnext_keyid); 574 + if (!*key) 575 + return -ENOENT; 576 + *traffic_key = kmalloc(tcp_ao_digest_size(*key), GFP_ATOMIC); 577 + if (!*traffic_key) 578 + return -ENOMEM; 579 + *allocated_traffic_key = true; 580 + if (tcp_ao_calc_key_skb(*key, *traffic_key, skb, 581 + sisn, disn, family)) 582 + return -1; 583 + *keyid = (*key)->rcvid; 584 + } else { 585 + struct tcp_ao_key *rnext_key; 617 586 618 - *key = tcp_ao_established_key(ao_info, aoh->rnext_keyid, -1); 619 - if (!*key) 620 - return -ENOENT; 621 - *traffic_key = snd_other_key(*key); 622 - rnext_key = READ_ONCE(ao_info->rnext_key); 623 - *keyid = rnext_key->rcvid; 624 - *sne = 0; 587 + if (sk->sk_state == TCP_TIME_WAIT) 588 + ao_info = rcu_dereference(tcp_twsk(sk)->ao_info); 589 + else 590 + ao_info = rcu_dereference(tcp_sk(sk)->ao_info); 591 + if (!ao_info) 592 + return -ENOENT; 625 593 594 + *key = tcp_ao_established_key(ao_info, aoh->rnext_keyid, -1); 595 + if (!*key) 596 + return -ENOENT; 597 + *traffic_key = snd_other_key(*key); 598 + rnext_key = READ_ONCE(ao_info->rnext_key); 599 + *keyid = rnext_key->rcvid; 600 + *sne = 0; 601 + } 626 602 return 0; 627 603 } 628 604 ··· 697 595 hash_location - (u8 *)th, 0); 698 596 kfree(tkey_buf); 699 597 return 0; 598 + } 599 + 600 + static struct tcp_ao_key *tcp_ao_inbound_lookup(unsigned short int family, 601 + const struct sock *sk, const struct sk_buff *skb, 602 + int sndid, int rcvid) 603 + { 604 + if (family == AF_INET) { 605 + const struct iphdr *iph = ip_hdr(skb); 606 + 607 + return tcp_ao_do_lookup(sk, (union tcp_ao_addr *)&iph->saddr, 608 + AF_INET, sndid, rcvid); 609 + } else { 610 + const struct ipv6hdr *iph = ipv6_hdr(skb); 611 + 612 + return tcp_ao_do_lookup(sk, (union tcp_ao_addr *)&iph->saddr, 613 + AF_INET6, sndid, rcvid); 614 + } 615 + } 616 + 617 + void tcp_ao_syncookie(struct sock *sk, const struct sk_buff *skb, 618 + struct tcp_request_sock *treq, 619 + unsigned short int family) 620 + { 621 + const struct tcphdr *th = tcp_hdr(skb); 622 + const struct tcp_ao_hdr *aoh; 623 + struct tcp_ao_key *key; 624 + 625 + treq->maclen = 0; 626 + 627 + if (tcp_parse_auth_options(th, NULL, &aoh) || !aoh) 628 + return; 629 + 630 + key = tcp_ao_inbound_lookup(family, sk, skb, -1, aoh->keyid); 631 + if (!key) 632 + /* Key not found, continue without TCP-AO */ 633 + return; 634 + 635 + treq->ao_rcv_next = aoh->keyid; 636 + treq->ao_keyid = aoh->rnext_keyid; 637 + treq->maclen = tcp_ao_maclen(key); 700 638 } 701 639 702 640 static int tcp_ao_cache_traffic_keys(const struct sock *sk, ··· 844 702 845 703 hlist_for_each_entry_rcu(key, &ao->head, node) 846 704 tcp_ao_cache_traffic_keys(sk, ao, key); 705 + } 706 + 707 + int tcp_ao_copy_all_matching(const struct sock *sk, struct sock *newsk, 708 + struct request_sock *req, struct sk_buff *skb, 709 + int family) 710 + { 711 + struct tcp_ao_key *key, *new_key, *first_key; 712 + struct tcp_ao_info *new_ao, *ao; 713 + struct hlist_node *key_head; 714 + union tcp_ao_addr *addr; 715 + bool match = false; 716 + int ret = -ENOMEM; 717 + 718 + ao = rcu_dereference(tcp_sk(sk)->ao_info); 719 + if (!ao) 720 + return 0; 721 + 722 + /* New socket without TCP-AO on it */ 723 + if (!tcp_rsk_used_ao(req)) 724 + return 0; 725 + 726 + new_ao = tcp_ao_alloc_info(GFP_ATOMIC); 727 + if (!new_ao) 728 + return -ENOMEM; 729 + new_ao->lisn = htonl(tcp_rsk(req)->snt_isn); 730 + new_ao->risn = htonl(tcp_rsk(req)->rcv_isn); 731 + new_ao->ao_required = ao->ao_required; 732 + 733 + if (family == AF_INET) { 734 + addr = (union tcp_ao_addr *)&newsk->sk_daddr; 735 + #if IS_ENABLED(CONFIG_IPV6) 736 + } else if (family == AF_INET6) { 737 + addr = (union tcp_ao_addr *)&newsk->sk_v6_daddr; 738 + #endif 739 + } else { 740 + ret = -EAFNOSUPPORT; 741 + goto free_ao; 742 + } 743 + 744 + hlist_for_each_entry_rcu(key, &ao->head, node) { 745 + if (tcp_ao_key_cmp(key, addr, key->prefixlen, family, -1, -1)) 746 + continue; 747 + 748 + new_key = tcp_ao_copy_key(newsk, key); 749 + if (!new_key) 750 + goto free_and_exit; 751 + 752 + tcp_ao_cache_traffic_keys(newsk, new_ao, new_key); 753 + tcp_ao_link_mkt(new_ao, new_key); 754 + match = true; 755 + } 756 + 757 + if (!match) { 758 + /* RFC5925 (7.4.1) specifies that the TCP-AO status 759 + * of a connection is determined on the initial SYN. 760 + * At this point the connection was TCP-AO enabled, so 761 + * it can't switch to being unsigned if peer's key 762 + * disappears on the listening socket. 763 + */ 764 + ret = -EKEYREJECTED; 765 + goto free_and_exit; 766 + } 767 + 768 + key_head = rcu_dereference(hlist_first_rcu(&new_ao->head)); 769 + first_key = hlist_entry_safe(key_head, struct tcp_ao_key, node); 770 + 771 + key = tcp_ao_established_key(new_ao, tcp_rsk(req)->ao_keyid, -1); 772 + if (key) 773 + new_ao->current_key = key; 774 + else 775 + new_ao->current_key = first_key; 776 + 777 + /* set rnext_key */ 778 + key = tcp_ao_established_key(new_ao, -1, tcp_rsk(req)->ao_rcv_next); 779 + if (key) 780 + new_ao->rnext_key = key; 781 + else 782 + new_ao->rnext_key = first_key; 783 + 784 + sk_gso_disable(newsk); 785 + rcu_assign_pointer(tcp_sk(newsk)->ao_info, new_ao); 786 + 787 + return 0; 788 + 789 + free_and_exit: 790 + hlist_for_each_entry_safe(key, key_head, &new_ao->head, node) { 791 + hlist_del(&key->node); 792 + tcp_sigpool_release(key->tcp_sigpool_id); 793 + atomic_sub(tcp_ao_sizeof_key(key), &newsk->sk_omem_alloc); 794 + kfree_sensitive(key); 795 + } 796 + free_ao: 797 + kfree(new_ao); 798 + return ret; 847 799 } 848 800 849 801 static bool tcp_ao_can_set_current_rnext(struct sock *sk)
+15
net/ipv4/tcp_input.c
··· 7045 7045 struct flowi fl; 7046 7046 u8 syncookies; 7047 7047 7048 + #ifdef CONFIG_TCP_AO 7049 + const struct tcp_ao_hdr *aoh; 7050 + #endif 7051 + 7048 7052 syncookies = READ_ONCE(net->ipv4.sysctl_tcp_syncookies); 7049 7053 7050 7054 /* TW buckets are converted to open requests without ··· 7135 7131 inet_rsk(req)->ecn_ok = 0; 7136 7132 } 7137 7133 7134 + #ifdef CONFIG_TCP_AO 7135 + if (tcp_parse_auth_options(tcp_hdr(skb), NULL, &aoh)) 7136 + goto drop_and_release; /* Invalid TCP options */ 7137 + if (aoh) { 7138 + tcp_rsk(req)->maclen = aoh->length - sizeof(struct tcp_ao_hdr); 7139 + tcp_rsk(req)->ao_rcv_next = aoh->keyid; 7140 + tcp_rsk(req)->ao_keyid = aoh->rnext_keyid; 7141 + } else { 7142 + tcp_rsk(req)->maclen = 0; 7143 + } 7144 + #endif 7138 7145 tcp_rsk(req)->snt_isn = isn; 7139 7146 tcp_rsk(req)->txhash = net_tx_rndhash(); 7140 7147 tcp_rsk(req)->syn_tos = TCP_SKB_CB(skb)->ip_dsfield;
+58 -8
net/ipv4/tcp_ipv4.c
··· 1072 1072 u32 seq = (sk->sk_state == TCP_LISTEN) ? tcp_rsk(req)->snt_isn + 1 : 1073 1073 tcp_sk(sk)->snd_nxt; 1074 1074 1075 - /* RFC 7323 2.3 1076 - * The window field (SEG.WND) of every outgoing segment, with the 1077 - * exception of <SYN> segments, MUST be right-shifted by 1078 - * Rcv.Wind.Shift bits: 1079 - */ 1075 + #ifdef CONFIG_TCP_AO 1076 + if (tcp_rsk_used_ao(req)) { 1077 + const union tcp_md5_addr *addr; 1078 + const struct tcp_ao_hdr *aoh; 1079 + 1080 + /* Invalid TCP option size or twice included auth */ 1081 + if (tcp_parse_auth_options(tcp_hdr(skb), NULL, &aoh)) 1082 + return; 1083 + if (!aoh) 1084 + return; 1085 + 1086 + addr = (union tcp_md5_addr *)&ip_hdr(skb)->saddr; 1087 + key.ao_key = tcp_ao_do_lookup(sk, addr, AF_INET, 1088 + aoh->rnext_keyid, -1); 1089 + if (unlikely(!key.ao_key)) { 1090 + /* Send ACK with any matching MKT for the peer */ 1091 + key.ao_key = tcp_ao_do_lookup(sk, addr, AF_INET, -1, -1); 1092 + /* Matching key disappeared (user removed the key?) 1093 + * let the handshake timeout. 1094 + */ 1095 + if (!key.ao_key) { 1096 + net_info_ratelimited("TCP-AO key for (%pI4, %d)->(%pI4, %d) suddenly disappeared, won't ACK new connection\n", 1097 + addr, 1098 + ntohs(tcp_hdr(skb)->source), 1099 + &ip_hdr(skb)->daddr, 1100 + ntohs(tcp_hdr(skb)->dest)); 1101 + return; 1102 + } 1103 + } 1104 + key.traffic_key = kmalloc(tcp_ao_digest_size(key.ao_key), GFP_ATOMIC); 1105 + if (!key.traffic_key) 1106 + return; 1107 + 1108 + key.type = TCP_KEY_AO; 1109 + key.rcv_next = aoh->keyid; 1110 + tcp_v4_ao_calc_key_rsk(key.ao_key, key.traffic_key, req); 1111 + #else 1112 + if (0) { 1113 + #endif 1080 1114 #ifdef CONFIG_TCP_MD5SIG 1081 - if (static_branch_unlikely(&tcp_md5_needed.key)) { 1115 + } else if (static_branch_unlikely(&tcp_md5_needed.key)) { 1082 1116 const union tcp_md5_addr *addr; 1083 1117 int l3index; 1084 1118 ··· 1121 1087 key.md5_key = tcp_md5_do_lookup(sk, l3index, addr, AF_INET); 1122 1088 if (key.md5_key) 1123 1089 key.type = TCP_KEY_MD5; 1124 - } 1125 1090 #endif 1091 + } 1092 + 1093 + /* RFC 7323 2.3 1094 + * The window field (SEG.WND) of every outgoing segment, with the 1095 + * exception of <SYN> segments, MUST be right-shifted by 1096 + * Rcv.Wind.Shift bits: 1097 + */ 1126 1098 tcp_v4_send_ack(sk, skb, seq, 1127 1099 tcp_rsk(req)->rcv_nxt, 1128 1100 req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale, ··· 1138 1098 inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0, 1139 1099 ip_hdr(skb)->tos, 1140 1100 READ_ONCE(tcp_rsk(req)->txhash)); 1101 + if (tcp_key_is_ao(&key)) 1102 + kfree(key.traffic_key); 1141 1103 } 1142 1104 1143 1105 /* ··· 1678 1636 .req_md5_lookup = tcp_v4_md5_lookup, 1679 1637 .calc_md5_hash = tcp_v4_md5_hash_skb, 1680 1638 #endif 1639 + #ifdef CONFIG_TCP_AO 1640 + .ao_lookup = tcp_v4_ao_lookup_rsk, 1641 + .ao_calc_key = tcp_v4_ao_calc_key_rsk, 1642 + #endif 1681 1643 #ifdef CONFIG_SYN_COOKIES 1682 1644 .cookie_init_seq = cookie_v4_init_sequence, 1683 1645 #endif ··· 1783 1737 /* Copy over the MD5 key from the original socket */ 1784 1738 addr = (union tcp_md5_addr *)&newinet->inet_daddr; 1785 1739 key = tcp_md5_do_lookup(sk, l3index, addr, AF_INET); 1786 - if (key) { 1740 + if (key && !tcp_rsk_used_ao(req)) { 1787 1741 if (tcp_md5_key_copy(newsk, addr, AF_INET, 32, l3index, key)) 1788 1742 goto put_and_exit; 1789 1743 sk_gso_disable(newsk); 1790 1744 } 1745 + #endif 1746 + #ifdef CONFIG_TCP_AO 1747 + if (tcp_ao_copy_all_matching(sk, newsk, req, skb, AF_INET)) 1748 + goto put_and_exit; /* OOM, release back memory */ 1791 1749 #endif 1792 1750 1793 1751 if (__inet_inherit_port(sk, newsk) < 0)
+10
net/ipv4/tcp_minisocks.c
··· 506 506 const struct tcp_sock *oldtp; 507 507 struct tcp_sock *newtp; 508 508 u32 seq; 509 + #ifdef CONFIG_TCP_AO 510 + struct tcp_ao_key *ao_key; 511 + #endif 509 512 510 513 if (!newsk) 511 514 return NULL; ··· 597 594 #ifdef CONFIG_TCP_MD5SIG 598 595 newtp->md5sig_info = NULL; /*XXX*/ 599 596 #endif 597 + #ifdef CONFIG_TCP_AO 598 + newtp->ao_info = NULL; 599 + ao_key = treq->af_specific->ao_lookup(sk, req, 600 + tcp_rsk(req)->ao_keyid, -1); 601 + if (ao_key) 602 + newtp->tcp_header_len += tcp_ao_len(ao_key); 603 + #endif 600 604 if (skb->len >= TCP_MSS_DEFAULT + newtp->tcp_header_len) 601 605 newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len; 602 606 newtp->rx_opt.mss_clamp = req->mss;
+23 -14
net/ipv4/tcp_output.c
··· 615 615 * (but it may well be that other scenarios fail similarly). 616 616 */ 617 617 static void tcp_options_write(struct tcphdr *th, struct tcp_sock *tp, 618 + const struct tcp_request_sock *tcprsk, 618 619 struct tcp_out_options *opts, 619 620 struct tcp_key *key) 620 621 { ··· 630 629 ptr += 4; 631 630 } else if (tcp_key_is_ao(key)) { 632 631 #ifdef CONFIG_TCP_AO 633 - struct tcp_ao_key *rnext_key; 634 - struct tcp_ao_info *ao_info; 635 - u8 maclen; 632 + u8 maclen = tcp_ao_maclen(key->ao_key); 636 633 637 - ao_info = rcu_dereference_check(tp->ao_info, 634 + if (tcprsk) { 635 + u8 aolen = maclen + sizeof(struct tcp_ao_hdr); 636 + 637 + *ptr++ = htonl((TCPOPT_AO << 24) | (aolen << 16) | 638 + (tcprsk->ao_keyid << 8) | 639 + (tcprsk->ao_rcv_next)); 640 + } else { 641 + struct tcp_ao_key *rnext_key; 642 + struct tcp_ao_info *ao_info; 643 + 644 + ao_info = rcu_dereference_check(tp->ao_info, 638 645 lockdep_sock_is_held(&tp->inet_conn.icsk_inet.sk)); 639 - rnext_key = READ_ONCE(ao_info->rnext_key); 640 - if (WARN_ON_ONCE(!rnext_key)) 641 - goto out_ao; 642 - maclen = tcp_ao_maclen(key->ao_key); 643 - *ptr++ = htonl((TCPOPT_AO << 24) | 644 - (tcp_ao_len(key->ao_key) << 16) | 645 - (key->ao_key->sndid << 8) | 646 - (rnext_key->rcvid)); 646 + rnext_key = READ_ONCE(ao_info->rnext_key); 647 + if (WARN_ON_ONCE(!rnext_key)) 648 + goto out_ao; 649 + *ptr++ = htonl((TCPOPT_AO << 24) | 650 + (tcp_ao_len(key->ao_key) << 16) | 651 + (key->ao_key->sndid << 8) | 652 + (rnext_key->rcvid)); 653 + } 647 654 opts->hash_location = (__u8 *)ptr; 648 655 ptr += maclen / sizeof(*ptr); 649 656 if (unlikely(maclen % sizeof(*ptr))) { ··· 1395 1386 th->window = htons(min(tp->rcv_wnd, 65535U)); 1396 1387 } 1397 1388 1398 - tcp_options_write(th, tp, &opts, &key); 1389 + tcp_options_write(th, tp, NULL, &opts, &key); 1399 1390 1400 1391 if (tcp_key_is_md5(&key)) { 1401 1392 #ifdef CONFIG_TCP_MD5SIG ··· 3738 3729 3739 3730 /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */ 3740 3731 th->window = htons(min(req->rsk_rcv_wnd, 65535U)); 3741 - tcp_options_write(th, NULL, &opts, &key); 3732 + tcp_options_write(th, NULL, NULL, &opts, &key); 3742 3733 th->doff = (tcp_header_size >> 2); 3743 3734 TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); 3744 3735
+2
net/ipv6/syncookies.c
··· 214 214 treq->snt_isn = cookie; 215 215 treq->ts_off = 0; 216 216 treq->txhash = net_tx_rndhash(); 217 + tcp_ao_syncookie(sk, skb, treq, AF_INET6); 218 + 217 219 if (IS_ENABLED(CONFIG_SMC)) 218 220 ireq->smc_ok = 0; 219 221
+35 -3
net/ipv6/tcp_ao.c
··· 49 49 return err; 50 50 } 51 51 52 + int tcp_v6_ao_calc_key_skb(struct tcp_ao_key *mkt, u8 *key, 53 + const struct sk_buff *skb, 54 + __be32 sisn, __be32 disn) 55 + { 56 + const struct ipv6hdr *iph = ipv6_hdr(skb); 57 + const struct tcphdr *th = tcp_hdr(skb); 58 + 59 + return tcp_v6_ao_calc_key(mkt, key, &iph->saddr, &iph->daddr, 60 + th->source, th->dest, sisn, disn); 61 + } 62 + 52 63 int tcp_v6_ao_calc_key_sk(struct tcp_ao_key *mkt, u8 *key, 53 64 const struct sock *sk, __be32 sisn, 54 65 __be32 disn, bool send) ··· 74 63 htons(sk->sk_num), disn, sisn); 75 64 } 76 65 77 - static struct tcp_ao_key *tcp_v6_ao_do_lookup(const struct sock *sk, 78 - const struct in6_addr *addr, 79 - int sndid, int rcvid) 66 + int tcp_v6_ao_calc_key_rsk(struct tcp_ao_key *mkt, u8 *key, 67 + struct request_sock *req) 68 + { 69 + struct inet_request_sock *ireq = inet_rsk(req); 70 + 71 + return tcp_v6_ao_calc_key(mkt, key, 72 + &ireq->ir_v6_loc_addr, &ireq->ir_v6_rmt_addr, 73 + htons(ireq->ir_num), ireq->ir_rmt_port, 74 + htonl(tcp_rsk(req)->snt_isn), 75 + htonl(tcp_rsk(req)->rcv_isn)); 76 + } 77 + 78 + struct tcp_ao_key *tcp_v6_ao_do_lookup(const struct sock *sk, 79 + const struct in6_addr *addr, 80 + int sndid, int rcvid) 80 81 { 81 82 return tcp_ao_do_lookup(sk, (union tcp_ao_addr *)addr, AF_INET6, 82 83 sndid, rcvid); ··· 99 76 int sndid, int rcvid) 100 77 { 101 78 struct in6_addr *addr = &addr_sk->sk_v6_daddr; 79 + 80 + return tcp_v6_ao_do_lookup(sk, addr, sndid, rcvid); 81 + } 82 + 83 + struct tcp_ao_key *tcp_v6_ao_lookup_rsk(const struct sock *sk, 84 + struct request_sock *req, 85 + int sndid, int rcvid) 86 + { 87 + struct in6_addr *addr = &inet_rsk(req)->ir_v6_rmt_addr; 102 88 103 89 return tcp_v6_ao_do_lookup(sk, addr, sndid, rcvid); 104 90 }
+62 -11
net/ipv6/tcp_ipv6.c
··· 836 836 .req_md5_lookup = tcp_v6_md5_lookup, 837 837 .calc_md5_hash = tcp_v6_md5_hash_skb, 838 838 #endif 839 + #ifdef CONFIG_TCP_AO 840 + .ao_lookup = tcp_v6_ao_lookup_rsk, 841 + .ao_calc_key = tcp_v6_ao_calc_key_rsk, 842 + #endif 839 843 #ifdef CONFIG_SYN_COOKIES 840 844 .cookie_init_seq = cookie_v6_init_sequence, 841 845 #endif ··· 1196 1192 { 1197 1193 struct tcp_key key = {}; 1198 1194 1195 + #ifdef CONFIG_TCP_AO 1196 + if (tcp_rsk_used_ao(req)) { 1197 + const struct in6_addr *addr = &ipv6_hdr(skb)->saddr; 1198 + const struct tcp_ao_hdr *aoh; 1199 + int l3index; 1200 + 1201 + l3index = tcp_v6_sdif(skb) ? tcp_v6_iif_l3_slave(skb) : 0; 1202 + /* Invalid TCP option size or twice included auth */ 1203 + if (tcp_parse_auth_options(tcp_hdr(skb), NULL, &aoh)) 1204 + return; 1205 + if (!aoh) 1206 + return; 1207 + key.ao_key = tcp_v6_ao_do_lookup(sk, addr, aoh->rnext_keyid, -1); 1208 + if (unlikely(!key.ao_key)) { 1209 + /* Send ACK with any matching MKT for the peer */ 1210 + key.ao_key = tcp_v6_ao_do_lookup(sk, addr, -1, -1); 1211 + /* Matching key disappeared (user removed the key?) 1212 + * let the handshake timeout. 1213 + */ 1214 + if (!key.ao_key) { 1215 + net_info_ratelimited("TCP-AO key for (%pI6, %d)->(%pI6, %d) suddenly disappeared, won't ACK new connection\n", 1216 + addr, 1217 + ntohs(tcp_hdr(skb)->source), 1218 + &ipv6_hdr(skb)->daddr, 1219 + ntohs(tcp_hdr(skb)->dest)); 1220 + return; 1221 + } 1222 + } 1223 + key.traffic_key = kmalloc(tcp_ao_digest_size(key.ao_key), GFP_ATOMIC); 1224 + if (!key.traffic_key) 1225 + return; 1226 + 1227 + key.type = TCP_KEY_AO; 1228 + key.rcv_next = aoh->keyid; 1229 + tcp_v6_ao_calc_key_rsk(key.ao_key, key.traffic_key, req); 1230 + #else 1231 + if (0) { 1232 + #endif 1199 1233 #ifdef CONFIG_TCP_MD5SIG 1200 - if (static_branch_unlikely(&tcp_md5_needed.key)) { 1234 + } else if (static_branch_unlikely(&tcp_md5_needed.key)) { 1201 1235 int l3index = tcp_v6_sdif(skb) ? tcp_v6_iif_l3_slave(skb) : 0; 1202 1236 1203 1237 key.md5_key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr, 1204 1238 l3index); 1205 1239 if (key.md5_key) 1206 1240 key.type = TCP_KEY_MD5; 1207 - } 1208 1241 #endif 1242 + } 1209 1243 1210 1244 /* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV 1211 1245 * sk->sk_state == TCP_SYN_RECV -> for Fast Open. ··· 1262 1220 &key, ipv6_get_dsfield(ipv6_hdr(skb)), 0, 1263 1221 READ_ONCE(sk->sk_priority), 1264 1222 READ_ONCE(tcp_rsk(req)->txhash)); 1223 + if (tcp_key_is_ao(&key)) 1224 + kfree(key.traffic_key); 1265 1225 } 1266 1226 1267 1227 ··· 1493 1449 #ifdef CONFIG_TCP_MD5SIG 1494 1450 l3index = l3mdev_master_ifindex_by_index(sock_net(sk), ireq->ir_iif); 1495 1451 1496 - /* Copy over the MD5 key from the original socket */ 1497 - key = tcp_v6_md5_do_lookup(sk, &newsk->sk_v6_daddr, l3index); 1498 - if (key) { 1499 - const union tcp_md5_addr *addr; 1452 + if (!tcp_rsk_used_ao(req)) { 1453 + /* Copy over the MD5 key from the original socket */ 1454 + key = tcp_v6_md5_do_lookup(sk, &newsk->sk_v6_daddr, l3index); 1455 + if (key) { 1456 + const union tcp_md5_addr *addr; 1500 1457 1501 - addr = (union tcp_md5_addr *)&newsk->sk_v6_daddr; 1502 - if (tcp_md5_key_copy(newsk, addr, AF_INET6, 128, l3index, key)) { 1503 - inet_csk_prepare_forced_close(newsk); 1504 - tcp_done(newsk); 1505 - goto out; 1458 + addr = (union tcp_md5_addr *)&newsk->sk_v6_daddr; 1459 + if (tcp_md5_key_copy(newsk, addr, AF_INET6, 128, l3index, key)) { 1460 + inet_csk_prepare_forced_close(newsk); 1461 + tcp_done(newsk); 1462 + goto out; 1463 + } 1506 1464 } 1507 1465 } 1466 + #endif 1467 + #ifdef CONFIG_TCP_AO 1468 + /* Copy over tcp_ao_info if any */ 1469 + if (tcp_ao_copy_all_matching(sk, newsk, req, skb, AF_INET6)) 1470 + goto out; /* OOM */ 1508 1471 #endif 1509 1472 1510 1473 if (__inet_inherit_port(sk, newsk) < 0) {