Steffen Klassert says: ==================== pull request (net): ipsec 2022-03-09 1) Fix IPv6 PMTU discovery for xfrm interfaces. From Lina Wang. 2) Revert failing for policies and states that are configured with XFRMA_IF_ID 0. It broke a user configuration. From Kai Lueke. 3) Fix a possible buffer overflow in the ESP output path. 4) Fix ESP GSO for tunnel and BEET mode on inter address family tunnels. ====================
Unified · Split
| @@ -4602,6 +4602,8 @@ int skb_csum_hwoffload_help(struct sk_buff *skb, · 4601 unmodified lines | |||
| 4602 | 4602 | ||
| 4603 | struct sk_buff *__skb_gso_segment(struct sk_buff *skb, | 4603 | struct sk_buff *__skb_gso_segment(struct sk_buff *skb, |
| 4604 | netdev_features_t features, bool tx_path); | 4604 | netdev_features_t features, bool tx_path); |
| 4605 | struct sk_buff *skb_eth_gso_segment(struct sk_buff *skb, | ||
| 4606 | netdev_features_t features, __be16 type); | ||
| 4605 | struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb, | 4607 | struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb, |
| 4606 | netdev_features_t features); | 4608 | netdev_features_t features); |
| 4607 | 4609 | ||
| @@ -4,6 +4,8 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | #include <linux/skbuff.h> | 5 | #include <linux/skbuff.h> |
| 6 | 6 | ||
| 7 | #define ESP_SKB_FRAG_MAXSIZE (PAGE_SIZE << SKB_FRAG_PAGE_ORDER) | ||
| 8 | |||
| 7 | struct ip_esp_hdr; | 9 | struct ip_esp_hdr; |
| 8 | 10 | ||
| 9 | static inline struct ip_esp_hdr *ip_esp_hdr(const struct sk_buff *skb) | 11 | static inline struct ip_esp_hdr *ip_esp_hdr(const struct sk_buff *skb) |
| @@ -92,6 +92,31 @@ void dev_remove_offload(struct packet_offload *po) · 91 unmodified lines | |||
| 92 | } | 92 | } |
| 93 | EXPORT_SYMBOL(dev_remove_offload); | 93 | EXPORT_SYMBOL(dev_remove_offload); |
| 94 | 94 | ||
| 95 | /** | ||
| 96 | * skb_eth_gso_segment - segmentation handler for ethernet protocols. | ||
| 97 | * @skb: buffer to segment | ||
| 98 | * @features: features for the output path (see dev->features) | ||
| 99 | * @type: Ethernet Protocol ID | ||
| 100 | */ | ||
| 101 | struct sk_buff *skb_eth_gso_segment(struct sk_buff *skb, | ||
| 102 | netdev_features_t features, __be16 type) | ||
| 103 | { | ||
| 104 | struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT); | ||
| 105 | struct packet_offload *ptype; | ||
| 106 | |||
| 107 | rcu_read_lock(); | ||
| 108 | list_for_each_entry_rcu(ptype, &offload_base, list) { | ||
| 109 | if (ptype->type == type && ptype->callbacks.gso_segment) { | ||
| 110 | segs = ptype->callbacks.gso_segment(skb, features); | ||
| 111 | break; | ||
| 112 | } | ||
| 113 | } | ||
| 114 | rcu_read_unlock(); | ||
| 115 | |||
| 116 | return segs; | ||
| 117 | } | ||
| 118 | EXPORT_SYMBOL(skb_eth_gso_segment); | ||
| 119 | |||
| 95 | /** | 120 | /** |
| 96 | * skb_mac_gso_segment - mac layer segmentation handler. | 121 | * skb_mac_gso_segment - mac layer segmentation handler. |
| 97 | * @skb: buffer to segment | 122 | * @skb: buffer to segment |
| @@ -446,6 +446,7 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info * · 445 unmodified lines | |||
| 446 | struct page *page; | 446 | struct page *page; |
| 447 | struct sk_buff *trailer; | 447 | struct sk_buff *trailer; |
| 448 | int tailen = esp->tailen; | 448 | int tailen = esp->tailen; |
| 449 | unsigned int allocsz; | ||
| 449 | 450 | ||
| 450 | /* this is non-NULL only with TCP/UDP Encapsulation */ | 451 | /* this is non-NULL only with TCP/UDP Encapsulation */ |
| 451 | if (x->encap) { | 452 | if (x->encap) { |
| @@ -455,6 +456,10 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info * · 3 unmodified lines | |||
| 455 | return err; | 456 | return err; |
| 456 | } | 457 | } |
| 457 | 458 | ||
| 459 | allocsz = ALIGN(skb->data_len + tailen, L1_CACHE_BYTES); | ||
| 460 | if (allocsz > ESP_SKB_FRAG_MAXSIZE) | ||
| 461 | goto cow; | ||
| 462 | |||
| 458 | if (!skb_cloned(skb)) { | 463 | if (!skb_cloned(skb)) { |
| 459 | if (tailen <= skb_tailroom(skb)) { | 464 | if (tailen <= skb_tailroom(skb)) { |
| 460 | nfrags = 1; | 465 | nfrags = 1; |
| @@ -110,8 +110,7 @@ static struct sk_buff *xfrm4_tunnel_gso_segment(struct xfrm_state *x, · 109 unmodified lines | |||
| 110 | struct sk_buff *skb, | 110 | struct sk_buff *skb, |
| 111 | netdev_features_t features) | 111 | netdev_features_t features) |
| 112 | { | 112 | { |
| 113 | __skb_push(skb, skb->mac_len); | 113 | return skb_eth_gso_segment(skb, features, htons(ETH_P_IP)); |
| 114 | return skb_mac_gso_segment(skb, features); | ||
| 115 | } | 114 | } |
| 116 | 115 | ||
| 117 | static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x, | 116 | static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x, |
| @@ -160,6 +159,9 @@ static struct sk_buff *xfrm4_beet_gso_segment(struct xfrm_state *x, · 42 unmodified lines | |||
| 160 | skb_shinfo(skb)->gso_type |= SKB_GSO_TCPV4; | 159 | skb_shinfo(skb)->gso_type |= SKB_GSO_TCPV4; |
| 161 | } | 160 | } |
| 162 | 161 | ||
| 162 | if (proto == IPPROTO_IPV6) | ||
| 163 | skb_shinfo(skb)->gso_type |= SKB_GSO_IPXIP4; | ||
| 164 | |||
| 163 | __skb_pull(skb, skb_transport_offset(skb)); | 165 | __skb_pull(skb, skb_transport_offset(skb)); |
| 164 | ops = rcu_dereference(inet_offloads[proto]); | 166 | ops = rcu_dereference(inet_offloads[proto]); |
| 165 | if (likely(ops && ops->callbacks.gso_segment)) | 167 | if (likely(ops && ops->callbacks.gso_segment)) |
| @@ -482,6 +482,7 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info · 481 unmodified lines | |||
| 482 | struct page *page; | 482 | struct page *page; |
| 483 | struct sk_buff *trailer; | 483 | struct sk_buff *trailer; |
| 484 | int tailen = esp->tailen; | 484 | int tailen = esp->tailen; |
| 485 | unsigned int allocsz; | ||
| 485 | 486 | ||
| 486 | if (x->encap) { | 487 | if (x->encap) { |
| 487 | int err = esp6_output_encap(x, skb, esp); | 488 | int err = esp6_output_encap(x, skb, esp); |
| @@ -490,6 +491,10 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info · 2 unmodified lines | |||
| 490 | return err; | 491 | return err; |
| 491 | } | 492 | } |
| 492 | 493 | ||
| 494 | allocsz = ALIGN(skb->data_len + tailen, L1_CACHE_BYTES); | ||
| 495 | if (allocsz > ESP_SKB_FRAG_MAXSIZE) | ||
| 496 | goto cow; | ||
| 497 | |||
| 493 | if (!skb_cloned(skb)) { | 498 | if (!skb_cloned(skb)) { |
| 494 | if (tailen <= skb_tailroom(skb)) { | 499 | if (tailen <= skb_tailroom(skb)) { |
| 495 | nfrags = 1; | 500 | nfrags = 1; |
| @@ -145,8 +145,7 @@ static struct sk_buff *xfrm6_tunnel_gso_segment(struct xfrm_state *x, · 144 unmodified lines | |||
| 145 | struct sk_buff *skb, | 145 | struct sk_buff *skb, |
| 146 | netdev_features_t features) | 146 | netdev_features_t features) |
| 147 | { | 147 | { |
| 148 | __skb_push(skb, skb->mac_len); | 148 | return skb_eth_gso_segment(skb, features, htons(ETH_P_IPV6)); |
| 149 | return skb_mac_gso_segment(skb, features); | ||
| 150 | } | 149 | } |
| 151 | 150 | ||
| 152 | static struct sk_buff *xfrm6_transport_gso_segment(struct xfrm_state *x, | 151 | static struct sk_buff *xfrm6_transport_gso_segment(struct xfrm_state *x, |
| @@ -199,6 +198,9 @@ static struct sk_buff *xfrm6_beet_gso_segment(struct xfrm_state *x, · 46 unmodified lines | |||
| 199 | ipv6_skip_exthdr(skb, 0, &proto, &frag); | 198 | ipv6_skip_exthdr(skb, 0, &proto, &frag); |
| 200 | } | 199 | } |
| 201 | 200 | ||
| 201 | if (proto == IPPROTO_IPIP) | ||
| 202 | skb_shinfo(skb)->gso_type |= SKB_GSO_IPXIP6; | ||
| 203 | |||
| 202 | __skb_pull(skb, skb_transport_offset(skb)); | 204 | __skb_pull(skb, skb_transport_offset(skb)); |
| 203 | ops = rcu_dereference(inet6_offloads[proto]); | 205 | ops = rcu_dereference(inet6_offloads[proto]); |
| 204 | if (likely(ops && ops->callbacks.gso_segment)) | 206 | if (likely(ops && ops->callbacks.gso_segment)) |
| @@ -45,6 +45,19 @@ static int __xfrm6_output_finish(struct net *net, struct sock *sk, struct sk_buf · 44 unmodified lines | |||
| 45 | return xfrm_output(sk, skb); | 45 | return xfrm_output(sk, skb); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | static int xfrm6_noneed_fragment(struct sk_buff *skb) | ||
| 49 | { | ||
| 50 | struct frag_hdr *fh; | ||
| 51 | u8 prevhdr = ipv6_hdr(skb)->nexthdr; | ||
| 52 | |||
| 53 | if (prevhdr != NEXTHDR_FRAGMENT) | ||
| 54 | return 0; | ||
| 55 | fh = (struct frag_hdr *)(skb->data + sizeof(struct ipv6hdr)); | ||
| 56 | if (fh->nexthdr == NEXTHDR_ESP || fh->nexthdr == NEXTHDR_AUTH) | ||
| 57 | return 1; | ||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | |||
| 48 | static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb) | 61 | static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb) |
| 49 | { | 62 | { |
| 50 | struct dst_entry *dst = skb_dst(skb); | 63 | struct dst_entry *dst = skb_dst(skb); |
| @@ -73,6 +86,9 @@ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb) · 22 unmodified lines | |||
| 73 | xfrm6_local_rxpmtu(skb, mtu); | 86 | xfrm6_local_rxpmtu(skb, mtu); |
| 74 | kfree_skb(skb); | 87 | kfree_skb(skb); |
| 75 | return -EMSGSIZE; | 88 | return -EMSGSIZE; |
| 89 | } else if (toobig && xfrm6_noneed_fragment(skb)) { | ||
| 90 | skb->ignore_df = 1; | ||
| 91 | goto skip_frag; | ||
| 76 | } else if (!skb->ignore_df && toobig && skb->sk) { | 92 | } else if (!skb->ignore_df && toobig && skb->sk) { |
| 77 | xfrm_local_error(skb, mtu); | 93 | xfrm_local_error(skb, mtu); |
| 78 | kfree_skb(skb); | 94 | kfree_skb(skb); |
| @@ -304,7 +304,10 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) · 303 unmodified lines | |||
| 304 | if (mtu < IPV6_MIN_MTU) | 304 | if (mtu < IPV6_MIN_MTU) |
| 305 | mtu = IPV6_MIN_MTU; | 305 | mtu = IPV6_MIN_MTU; |
| 306 | 306 | ||
| 307 | icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); | 307 | if (skb->len > 1280) |
| 308 | icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); | ||
| 309 | else | ||
| 310 | goto xmit; | ||
| 308 | } else { | 311 | } else { |
| 309 | if (!(ip_hdr(skb)->frag_off & htons(IP_DF))) | 312 | if (!(ip_hdr(skb)->frag_off & htons(IP_DF))) |
| 310 | goto xmit; | 313 | goto xmit; |
| @@ -630,13 +630,8 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, · 629 unmodified lines | |||
| 630 | 630 | ||
| 631 | xfrm_smark_init(attrs, &x->props.smark); | 631 | xfrm_smark_init(attrs, &x->props.smark); |
| 632 | 632 | ||
| 633 | if (attrs[XFRMA_IF_ID]) { | 633 | if (attrs[XFRMA_IF_ID]) |
| 634 | x->if_id = nla_get_u32(attrs[XFRMA_IF_ID]); | 634 | x->if_id = nla_get_u32(attrs[XFRMA_IF_ID]); |
| 635 | if (!x->if_id) { | ||
| 636 | err = -EINVAL; | ||
| 637 | goto error; | ||
| 638 | } | ||
| 639 | } | ||
| 640 | 635 | ||
| 641 | err = __xfrm_init_state(x, false, attrs[XFRMA_OFFLOAD_DEV]); | 636 | err = __xfrm_init_state(x, false, attrs[XFRMA_OFFLOAD_DEV]); |
| 642 | if (err) | 637 | if (err) |
| @@ -1432,13 +1427,8 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, · 789 unmodified lines | |||
| 1432 | 1427 | ||
| 1433 | mark = xfrm_mark_get(attrs, &m); | 1428 | mark = xfrm_mark_get(attrs, &m); |
| 1434 | 1429 | ||
| 1435 | if (attrs[XFRMA_IF_ID]) { | 1430 | if (attrs[XFRMA_IF_ID]) |
| 1436 | if_id = nla_get_u32(attrs[XFRMA_IF_ID]); | 1431 | if_id = nla_get_u32(attrs[XFRMA_IF_ID]); |
| 1437 | if (!if_id) { | ||
| 1438 | err = -EINVAL; | ||
| 1439 | goto out_noput; | ||
| 1440 | } | ||
| 1441 | } | ||
| 1442 | 1432 | ||
| 1443 | if (p->info.seq) { | 1433 | if (p->info.seq) { |
| 1444 | x = xfrm_find_acq_byseq(net, mark, p->info.seq); | 1434 | x = xfrm_find_acq_byseq(net, mark, p->info.seq); |
| @@ -1751,13 +1741,8 @@ static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_us · 306 unmodified lines | |||
| 1751 | 1741 | ||
| 1752 | xfrm_mark_get(attrs, &xp->mark); | 1742 | xfrm_mark_get(attrs, &xp->mark); |
| 1753 | 1743 | ||
| 1754 | if (attrs[XFRMA_IF_ID]) { | 1744 | if (attrs[XFRMA_IF_ID]) |
| 1755 | xp->if_id = nla_get_u32(attrs[XFRMA_IF_ID]); | 1745 | xp->if_id = nla_get_u32(attrs[XFRMA_IF_ID]); |
| 1756 | if (!xp->if_id) { | ||
| 1757 | err = -EINVAL; | ||
| 1758 | goto error; | ||
| 1759 | } | ||
| 1760 | } | ||
| 1761 | 1746 | ||
| 1762 | return xp; | 1747 | return xp; |
| 1763 | error: | 1748 | error: |