History

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec

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. ====================

David S. Miller committed 4 years ago

Commit cc7e2f52 parents 71171ac 23c7f8d10 files · +70 −23Browse files

Unified · Split

10 files
  1. include/linux/netdevice.h +2 −0
  2. include/net/esp.h +2 −0
  3. net/core/gro.c +25 −0
  4. net/ipv4/esp4.c +5 −0
  5. net/ipv4/esp4_offload.c +4 −2
  6. net/ipv6/esp6.c +5 −0
  7. net/ipv6/esp6_offload.c +4 −2
  8. net/ipv6/xfrm6_output.c +16 −0
  9. net/xfrm/xfrm_interface.c +4 −1
  10. net/xfrm/xfrm_user.c +3 −18
include/linux/netdevice.h+2−0
@@ -4602,6 +4602,8 @@ int skb_csum_hwoffload_help(struct sk_buff *skb, · 4601 unmodified lines
4602 4602
4603struct sk_buff *__skb_gso_segment(struct sk_buff *skb,4603struct 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);
4605struct sk_buff *skb_eth_gso_segment(struct sk_buff *skb,
4606 netdev_features_t features, __be16 type);
4605struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb,4607struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb,
4606 netdev_features_t features);4608 netdev_features_t features);
4607 4609
include/net/esp.h+2−0
@@ -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
7struct ip_esp_hdr;9struct ip_esp_hdr;
8 10
9static inline struct ip_esp_hdr *ip_esp_hdr(const struct sk_buff *skb)11static inline struct ip_esp_hdr *ip_esp_hdr(const struct sk_buff *skb)
net/core/gro.c+25−0
@@ -92,6 +92,31 @@ void dev_remove_offload(struct packet_offload *po) · 91 unmodified lines
92}92}
93EXPORT_SYMBOL(dev_remove_offload);93EXPORT_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 */
101struct 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}
118EXPORT_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 segment122 * @skb: buffer to segment
net/ipv4/esp4.c+5−0
@@ -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;
net/ipv4/esp4_offload.c+4−2
@@ -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
117static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,116static 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))
net/ipv6/esp6.c+5−0
@@ -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;
net/ipv6/esp6_offload.c+4−2
@@ -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
152static struct sk_buff *xfrm6_transport_gso_segment(struct xfrm_state *x,151static 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))
net/ipv6/xfrm6_output.c+16−0
@@ -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
48static 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
48static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)61static 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);
net/xfrm/xfrm_interface.c+4−1
@@ -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;
net/xfrm/xfrm_user.c+3−18
@@ -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: