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

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Pablo Neira Ayuso says:

====================
Netfilter/IPVS updates for net-next

The following patchset container Netfilter/IPVS update for net-next:

1) Add UDP tunnel support for ICMP errors in IPVS.

Julian Anastasov says:

This patchset is a followup to the commit that adds UDP/GUE tunnel:
"ipvs: allow tunneling with gue encapsulation".

What we do is to put tunnel real servers in hash table (patch 1),
add function to lookup tunnels (patch 2) and use it to strip the
embedded tunnel headers from ICMP errors (patch 3).

2) Extend xt_owner to match for supplementary groups, from
Lukasz Pawelczyk.

3) Remove unused oif field in flow_offload_tuple object, from
Taehee Yoo.

4) Release basechain counters from workqueue to skip synchronize_rcu()
call. From Florian Westphal.

5) Replace skb_make_writable() by skb_ensure_writable(). Patchset
from Florian Westphal.

6) Checksum support for gue encapsulation in IPVS, from Jacky Hu.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+390 -150
-5
include/linux/netfilter.h
··· 336 336 char __user *opt, int *len); 337 337 #endif 338 338 339 - /* Call this before modifying an existing packet: ensures it is 340 - modifiable and linear to the point you care about (writable_len). 341 - Returns true or false. */ 342 - int skb_make_writable(struct sk_buff *skb, unsigned int writable_len); 343 - 344 339 struct flowi; 345 340 struct nf_queue_entry; 346 341
+8
include/net/ip_vs.h
··· 603 603 604 604 u16 tun_type; /* tunnel type */ 605 605 __be16 tun_port; /* tunnel port */ 606 + u16 tun_flags; /* tunnel flags */ 606 607 }; 607 608 608 609 ··· 666 665 atomic_t last_weight; /* server latest weight */ 667 666 __u16 tun_type; /* tunnel type */ 668 667 __be16 tun_port; /* tunnel port */ 668 + __u16 tun_flags; /* tunnel flags */ 669 669 670 670 refcount_t refcnt; /* reference counter */ 671 671 struct ip_vs_stats stats; /* statistics */ ··· 1406 1404 struct ip_vs_dest * 1407 1405 ip_vs_find_real_service(struct netns_ipvs *ipvs, int af, __u16 protocol, 1408 1406 const union nf_inet_addr *daddr, __be16 dport); 1407 + struct ip_vs_dest *ip_vs_find_tunnel(struct netns_ipvs *ipvs, int af, 1408 + const union nf_inet_addr *daddr, 1409 + __be16 tun_port); 1409 1410 1410 1411 int ip_vs_use_count_inc(void); 1411 1412 void ip_vs_use_count_dec(void); ··· 1501 1496 #else 1502 1497 static inline int ip_vs_todrop(struct netns_ipvs *ipvs) { return 0; } 1503 1498 #endif 1499 + 1500 + #define IP_VS_DFWD_METHOD(dest) (atomic_read(&(dest)->conn_flags) & \ 1501 + IP_VS_CONN_F_FWD_MASK) 1504 1502 1505 1503 /* ip_vs_fwd_tag returns the forwarding tag of the connection */ 1506 1504 #define IP_VS_FWD_METHOD(cp) (cp->flags & IP_VS_CONN_F_FWD_MASK)
-2
include/net/netfilter/nf_flow_table.h
··· 53 53 u8 l4proto; 54 54 u8 dir; 55 55 56 - int oifidx; 57 - 58 56 u16 mtu; 59 57 60 58 struct dst_entry *dst_cache;
+7
include/uapi/linux/ip_vs.h
··· 131 131 IP_VS_CONN_F_TUNNEL_TYPE_MAX, 132 132 }; 133 133 134 + /* Tunnel encapsulation flags */ 135 + #define IP_VS_TUNNEL_ENCAP_FLAG_NOCSUM (0) 136 + #define IP_VS_TUNNEL_ENCAP_FLAG_CSUM (1 << 0) 137 + #define IP_VS_TUNNEL_ENCAP_FLAG_REMCSUM (1 << 1) 138 + 134 139 /* 135 140 * The struct ip_vs_service_user and struct ip_vs_dest_user are 136 141 * used to set IPVS rules through setsockopt. ··· 407 402 IPVS_DEST_ATTR_TUN_TYPE, /* tunnel type */ 408 403 409 404 IPVS_DEST_ATTR_TUN_PORT, /* tunnel port */ 405 + 406 + IPVS_DEST_ATTR_TUN_FLAGS, /* tunnel flags */ 410 407 411 408 __IPVS_DEST_ATTR_MAX, 412 409 };
+4 -3
include/uapi/linux/netfilter/xt_owner.h
··· 5 5 #include <linux/types.h> 6 6 7 7 enum { 8 - XT_OWNER_UID = 1 << 0, 9 - XT_OWNER_GID = 1 << 1, 10 - XT_OWNER_SOCKET = 1 << 2, 8 + XT_OWNER_UID = 1 << 0, 9 + XT_OWNER_GID = 1 << 1, 10 + XT_OWNER_SOCKET = 1 << 2, 11 + XT_OWNER_SUPPL_GROUPS = 1 << 3, 11 12 }; 12 13 13 14 struct xt_owner_match_info {
+1 -1
net/bridge/netfilter/ebt_dnat.c
··· 22 22 const struct ebt_nat_info *info = par->targinfo; 23 23 struct net_device *dev; 24 24 25 - if (!skb_make_writable(skb, 0)) 25 + if (skb_ensure_writable(skb, ETH_ALEN)) 26 26 return EBT_DROP; 27 27 28 28 ether_addr_copy(eth_hdr(skb)->h_dest, info->mac);
+1 -1
net/bridge/netfilter/ebt_redirect.c
··· 21 21 { 22 22 const struct ebt_redirect_info *info = par->targinfo; 23 23 24 - if (!skb_make_writable(skb, 0)) 24 + if (skb_ensure_writable(skb, ETH_ALEN)) 25 25 return EBT_DROP; 26 26 27 27 if (xt_hooknum(par) != NF_BR_BROUTING)
+1 -1
net/bridge/netfilter/ebt_snat.c
··· 22 22 { 23 23 const struct ebt_nat_info *info = par->targinfo; 24 24 25 - if (!skb_make_writable(skb, 0)) 25 + if (skb_ensure_writable(skb, ETH_ALEN * 2)) 26 26 return EBT_DROP; 27 27 28 28 ether_addr_copy(eth_hdr(skb)->h_source, info->mac);
+1 -1
net/ipv4/netfilter/arpt_mangle.c
··· 17 17 unsigned char *arpptr; 18 18 int pln, hln; 19 19 20 - if (!skb_make_writable(skb, skb->len)) 20 + if (skb_ensure_writable(skb, skb->len)) 21 21 return NF_DROP; 22 22 23 23 arp = arp_hdr(skb);
+2 -2
net/ipv4/netfilter/ipt_ECN.c
··· 32 32 33 33 if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) { 34 34 __u8 oldtos; 35 - if (!skb_make_writable(skb, sizeof(struct iphdr))) 35 + if (skb_ensure_writable(skb, sizeof(struct iphdr))) 36 36 return false; 37 37 iph = ip_hdr(skb); 38 38 oldtos = iph->tos; ··· 61 61 tcph->cwr == einfo->proto.tcp.cwr)) 62 62 return true; 63 63 64 - if (!skb_make_writable(skb, ip_hdrlen(skb) + sizeof(*tcph))) 64 + if (skb_ensure_writable(skb, ip_hdrlen(skb) + sizeof(*tcph))) 65 65 return false; 66 66 tcph = (void *)ip_hdr(skb) + ip_hdrlen(skb); 67 67
+1 -1
net/ipv4/netfilter/nf_nat_h323.c
··· 59 59 net_notice_ratelimited("nf_nat_h323: nf_nat_mangle_udp_packet error\n"); 60 60 return -1; 61 61 } 62 - /* nf_nat_mangle_udp_packet uses skb_make_writable() to copy 62 + /* nf_nat_mangle_udp_packet uses skb_ensure_writable() to copy 63 63 * or pull everything in a linear buffer, so we can safely 64 64 * use the skb pointers now */ 65 65 *data = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);
+1 -1
net/ipv4/netfilter/nf_nat_snmp_basic_main.c
··· 186 186 return NF_DROP; 187 187 } 188 188 189 - if (!skb_make_writable(skb, skb->len)) { 189 + if (skb_ensure_writable(skb, skb->len)) { 190 190 nf_ct_helper_log(skb, ct, "cannot mangle packet"); 191 191 return NF_DROP; 192 192 }
-22
net/netfilter/core.c
··· 536 536 } 537 537 EXPORT_SYMBOL(nf_hook_slow); 538 538 539 - 540 - int skb_make_writable(struct sk_buff *skb, unsigned int writable_len) 541 - { 542 - if (writable_len > skb->len) 543 - return 0; 544 - 545 - /* Not exclusive use of packet? Must copy. */ 546 - if (!skb_cloned(skb)) { 547 - if (writable_len <= skb_headlen(skb)) 548 - return 1; 549 - } else if (skb_clone_writable(skb, writable_len)) 550 - return 1; 551 - 552 - if (writable_len <= skb_headlen(skb)) 553 - writable_len = 0; 554 - else 555 - writable_len -= skb_headlen(skb); 556 - 557 - return !!__pskb_pull_tail(skb, writable_len); 558 - } 559 - EXPORT_SYMBOL(skb_make_writable); 560 - 561 539 /* This needs to be compiled in any case to avoid dependencies between the 562 540 * nfnetlink_queue code and nf_conntrack. 563 541 */
+2 -2
net/netfilter/ipvs/ip_vs_app.c
··· 363 363 struct tcphdr *th; 364 364 __u32 seq; 365 365 366 - if (!skb_make_writable(skb, tcp_offset + sizeof(*th))) 366 + if (skb_ensure_writable(skb, tcp_offset + sizeof(*th))) 367 367 return 0; 368 368 369 369 th = (struct tcphdr *)(skb_network_header(skb) + tcp_offset); ··· 440 440 struct tcphdr *th; 441 441 __u32 seq; 442 442 443 - if (!skb_make_writable(skb, tcp_offset + sizeof(*th))) 443 + if (skb_ensure_writable(skb, tcp_offset + sizeof(*th))) 444 444 return 0; 445 445 446 446 th = (struct tcphdr *)(skb_network_header(skb) + tcp_offset);
+70 -2
net/netfilter/ipvs/ip_vs_core.c
··· 39 39 #include <net/tcp.h> 40 40 #include <net/udp.h> 41 41 #include <net/icmp.h> /* for icmp_send */ 42 + #include <net/gue.h> 42 43 #include <net/route.h> 43 44 #include <net/ip6_checksum.h> 44 45 #include <net/netns/generic.h> /* net_generic() */ ··· 898 897 if (IPPROTO_TCP == protocol || IPPROTO_UDP == protocol || 899 898 IPPROTO_SCTP == protocol) 900 899 offset += 2 * sizeof(__u16); 901 - if (!skb_make_writable(skb, offset)) 900 + if (skb_ensure_writable(skb, offset)) 902 901 goto out; 903 902 904 903 #ifdef CONFIG_IP_VS_IPV6 ··· 1288 1287 1289 1288 IP_VS_DBG_PKT(11, af, pp, skb, iph->off, "Outgoing packet"); 1290 1289 1291 - if (!skb_make_writable(skb, iph->len)) 1290 + if (skb_ensure_writable(skb, iph->len)) 1292 1291 goto drop; 1293 1292 1294 1293 /* mangle the packet */ ··· 1580 1579 return 1; 1581 1580 } 1582 1581 1582 + /* Check the UDP tunnel and return its header length */ 1583 + static int ipvs_udp_decap(struct netns_ipvs *ipvs, struct sk_buff *skb, 1584 + unsigned int offset, __u16 af, 1585 + const union nf_inet_addr *daddr, __u8 *proto) 1586 + { 1587 + struct udphdr _udph, *udph; 1588 + struct ip_vs_dest *dest; 1589 + 1590 + udph = skb_header_pointer(skb, offset, sizeof(_udph), &_udph); 1591 + if (!udph) 1592 + goto unk; 1593 + offset += sizeof(struct udphdr); 1594 + dest = ip_vs_find_tunnel(ipvs, af, daddr, udph->dest); 1595 + if (!dest) 1596 + goto unk; 1597 + if (dest->tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) { 1598 + struct guehdr _gueh, *gueh; 1599 + 1600 + gueh = skb_header_pointer(skb, offset, sizeof(_gueh), &_gueh); 1601 + if (!gueh) 1602 + goto unk; 1603 + if (gueh->control != 0 || gueh->version != 0) 1604 + goto unk; 1605 + /* Later we can support also IPPROTO_IPV6 */ 1606 + if (gueh->proto_ctype != IPPROTO_IPIP) 1607 + goto unk; 1608 + *proto = gueh->proto_ctype; 1609 + return sizeof(struct udphdr) + sizeof(struct guehdr) + 1610 + (gueh->hlen << 2); 1611 + } 1612 + 1613 + unk: 1614 + return 0; 1615 + } 1616 + 1583 1617 /* 1584 1618 * Handle ICMP messages in the outside-to-inside direction (incoming). 1585 1619 * Find any that might be relevant, check against existing connections, ··· 1634 1598 struct ip_vs_proto_data *pd; 1635 1599 unsigned int offset, offset2, ihl, verdict; 1636 1600 bool ipip, new_cp = false; 1601 + union nf_inet_addr *raddr; 1637 1602 1638 1603 *related = 1; 1639 1604 ··· 1673 1636 cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph); 1674 1637 if (cih == NULL) 1675 1638 return NF_ACCEPT; /* The packet looks wrong, ignore */ 1639 + raddr = (union nf_inet_addr *)&cih->daddr; 1676 1640 1677 1641 /* Special case for errors for IPIP packets */ 1678 1642 ipip = false; 1679 1643 if (cih->protocol == IPPROTO_IPIP) { 1644 + struct ip_vs_dest *dest; 1645 + 1680 1646 if (unlikely(cih->frag_off & htons(IP_OFFSET))) 1681 1647 return NF_ACCEPT; 1682 1648 /* Error for our IPIP must arrive at LOCAL_IN */ 1683 1649 if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL)) 1650 + return NF_ACCEPT; 1651 + dest = ip_vs_find_tunnel(ipvs, AF_INET, raddr, 0); 1652 + /* Only for known tunnel */ 1653 + if (!dest || dest->tun_type != IP_VS_CONN_F_TUNNEL_TYPE_IPIP) 1684 1654 return NF_ACCEPT; 1685 1655 offset += cih->ihl * 4; 1686 1656 cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph); 1687 1657 if (cih == NULL) 1688 1658 return NF_ACCEPT; /* The packet looks wrong, ignore */ 1689 1659 ipip = true; 1660 + } else if (cih->protocol == IPPROTO_UDP && /* Can be UDP encap */ 1661 + /* Error for our tunnel must arrive at LOCAL_IN */ 1662 + (skb_rtable(skb)->rt_flags & RTCF_LOCAL)) { 1663 + __u8 iproto; 1664 + int ulen; 1665 + 1666 + /* Non-first fragment has no UDP header */ 1667 + if (unlikely(cih->frag_off & htons(IP_OFFSET))) 1668 + return NF_ACCEPT; 1669 + offset2 = offset + cih->ihl * 4; 1670 + ulen = ipvs_udp_decap(ipvs, skb, offset2, AF_INET, raddr, 1671 + &iproto); 1672 + if (ulen > 0) { 1673 + /* Skip IP and UDP tunnel headers */ 1674 + offset = offset2 + ulen; 1675 + /* Now we should be at the original IP header */ 1676 + cih = skb_header_pointer(skb, offset, sizeof(_ciph), 1677 + &_ciph); 1678 + if (cih && cih->version == 4 && cih->ihl >= 5 && 1679 + iproto == IPPROTO_IPIP) 1680 + ipip = true; 1681 + else 1682 + return NF_ACCEPT; 1683 + } 1690 1684 } 1691 1685 1692 1686 pd = ip_vs_proto_data_get(ipvs, cih->protocol);
+74 -9
net/netfilter/ipvs/ip_vs_ctl.c
··· 515 515 static void ip_vs_rs_hash(struct netns_ipvs *ipvs, struct ip_vs_dest *dest) 516 516 { 517 517 unsigned int hash; 518 + __be16 port; 518 519 519 520 if (dest->in_rs_table) 520 521 return; 522 + 523 + switch (IP_VS_DFWD_METHOD(dest)) { 524 + case IP_VS_CONN_F_MASQ: 525 + port = dest->port; 526 + break; 527 + case IP_VS_CONN_F_TUNNEL: 528 + switch (dest->tun_type) { 529 + case IP_VS_CONN_F_TUNNEL_TYPE_GUE: 530 + port = dest->tun_port; 531 + break; 532 + case IP_VS_CONN_F_TUNNEL_TYPE_IPIP: 533 + port = 0; 534 + break; 535 + default: 536 + return; 537 + } 538 + break; 539 + default: 540 + return; 541 + } 521 542 522 543 /* 523 544 * Hash by proto,addr,port, 524 545 * which are the parameters of the real service. 525 546 */ 526 - hash = ip_vs_rs_hashkey(dest->af, &dest->addr, dest->port); 547 + hash = ip_vs_rs_hashkey(dest->af, &dest->addr, port); 527 548 528 549 hlist_add_head_rcu(&dest->d_list, &ipvs->rs_table[hash]); 529 550 dest->in_rs_table = 1; ··· 576 555 if (dest->port == dport && 577 556 dest->af == af && 578 557 ip_vs_addr_equal(af, &dest->addr, daddr) && 579 - (dest->protocol == protocol || dest->vfwmark)) { 558 + (dest->protocol == protocol || dest->vfwmark) && 559 + IP_VS_DFWD_METHOD(dest) == IP_VS_CONN_F_MASQ) { 580 560 /* HIT */ 581 561 return true; 582 562 } ··· 607 585 if (dest->port == dport && 608 586 dest->af == af && 609 587 ip_vs_addr_equal(af, &dest->addr, daddr) && 610 - (dest->protocol == protocol || dest->vfwmark)) { 588 + (dest->protocol == protocol || dest->vfwmark) && 589 + IP_VS_DFWD_METHOD(dest) == IP_VS_CONN_F_MASQ) { 590 + /* HIT */ 591 + return dest; 592 + } 593 + } 594 + 595 + return NULL; 596 + } 597 + 598 + /* Find real service record by <af,addr,tun_port>. 599 + * In case of multiple records with the same <af,addr,tun_port>, only 600 + * the first found record is returned. 601 + * 602 + * To be called under RCU lock. 603 + */ 604 + struct ip_vs_dest *ip_vs_find_tunnel(struct netns_ipvs *ipvs, int af, 605 + const union nf_inet_addr *daddr, 606 + __be16 tun_port) 607 + { 608 + struct ip_vs_dest *dest; 609 + unsigned int hash; 610 + 611 + /* Check for "full" addressed entries */ 612 + hash = ip_vs_rs_hashkey(af, daddr, tun_port); 613 + 614 + hlist_for_each_entry_rcu(dest, &ipvs->rs_table[hash], d_list) { 615 + if (dest->tun_port == tun_port && 616 + dest->af == af && 617 + ip_vs_addr_equal(af, &dest->addr, daddr) && 618 + IP_VS_DFWD_METHOD(dest) == IP_VS_CONN_F_TUNNEL) { 611 619 /* HIT */ 612 620 return dest; 613 621 } ··· 883 831 conn_flags = udest->conn_flags & IP_VS_CONN_F_DEST_MASK; 884 832 conn_flags |= IP_VS_CONN_F_INACTIVE; 885 833 834 + /* Need to rehash? */ 835 + if ((udest->conn_flags & IP_VS_CONN_F_FWD_MASK) != 836 + IP_VS_DFWD_METHOD(dest) || 837 + udest->tun_type != dest->tun_type || 838 + udest->tun_port != dest->tun_port) 839 + ip_vs_rs_unhash(dest); 840 + 886 841 /* set the tunnel info */ 887 842 dest->tun_type = udest->tun_type; 888 843 dest->tun_port = udest->tun_port; 844 + dest->tun_flags = udest->tun_flags; 889 845 890 846 /* set the IP_VS_CONN_F_NOOUTPUT flag if not masquerading/NAT */ 891 847 if ((conn_flags & IP_VS_CONN_F_FWD_MASK) != IP_VS_CONN_F_MASQ) { 892 848 conn_flags |= IP_VS_CONN_F_NOOUTPUT; 893 849 } else { 894 - /* 895 - * Put the real service in rs_table if not present. 896 - * For now only for NAT! 897 - */ 898 - ip_vs_rs_hash(ipvs, dest); 899 850 /* FTP-NAT requires conntrack for mangling */ 900 851 if (svc->port == FTPPORT) 901 852 ip_vs_register_conntrack(svc); 902 853 } 903 854 atomic_set(&dest->conn_flags, conn_flags); 855 + /* Put the real service in rs_table if not present. */ 856 + ip_vs_rs_hash(ipvs, dest); 904 857 905 858 /* bind the service */ 906 859 old_svc = rcu_dereference_protected(dest->svc, 1); ··· 2968 2911 [IPVS_DEST_ATTR_ADDR_FAMILY] = { .type = NLA_U16 }, 2969 2912 [IPVS_DEST_ATTR_TUN_TYPE] = { .type = NLA_U8 }, 2970 2913 [IPVS_DEST_ATTR_TUN_PORT] = { .type = NLA_U16 }, 2914 + [IPVS_DEST_ATTR_TUN_FLAGS] = { .type = NLA_U16 }, 2971 2915 }; 2972 2916 2973 2917 static int ip_vs_genl_fill_stats(struct sk_buff *skb, int container_type, ··· 3275 3217 dest->tun_type) || 3276 3218 nla_put_be16(skb, IPVS_DEST_ATTR_TUN_PORT, 3277 3219 dest->tun_port) || 3220 + nla_put_u16(skb, IPVS_DEST_ATTR_TUN_FLAGS, 3221 + dest->tun_flags) || 3278 3222 nla_put_u32(skb, IPVS_DEST_ATTR_U_THRESH, dest->u_threshold) || 3279 3223 nla_put_u32(skb, IPVS_DEST_ATTR_L_THRESH, dest->l_threshold) || 3280 3224 nla_put_u32(skb, IPVS_DEST_ATTR_ACTIVE_CONNS, ··· 3397 3337 /* If a full entry was requested, check for the additional fields */ 3398 3338 if (full_entry) { 3399 3339 struct nlattr *nla_fwd, *nla_weight, *nla_u_thresh, 3400 - *nla_l_thresh, *nla_tun_type, *nla_tun_port; 3340 + *nla_l_thresh, *nla_tun_type, *nla_tun_port, 3341 + *nla_tun_flags; 3401 3342 3402 3343 nla_fwd = attrs[IPVS_DEST_ATTR_FWD_METHOD]; 3403 3344 nla_weight = attrs[IPVS_DEST_ATTR_WEIGHT]; ··· 3406 3345 nla_l_thresh = attrs[IPVS_DEST_ATTR_L_THRESH]; 3407 3346 nla_tun_type = attrs[IPVS_DEST_ATTR_TUN_TYPE]; 3408 3347 nla_tun_port = attrs[IPVS_DEST_ATTR_TUN_PORT]; 3348 + nla_tun_flags = attrs[IPVS_DEST_ATTR_TUN_FLAGS]; 3409 3349 3410 3350 if (!(nla_fwd && nla_weight && nla_u_thresh && nla_l_thresh)) 3411 3351 return -EINVAL; ··· 3422 3360 3423 3361 if (nla_tun_port) 3424 3362 udest->tun_port = nla_get_be16(nla_tun_port); 3363 + 3364 + if (nla_tun_flags) 3365 + udest->tun_flags = nla_get_u16(nla_tun_flags); 3425 3366 } 3426 3367 3427 3368 return 0;
+2 -2
net/netfilter/ipvs/ip_vs_ftp.c
··· 273 273 return 1; 274 274 275 275 /* Linear packets are much easier to deal with. */ 276 - if (!skb_make_writable(skb, skb->len)) 276 + if (skb_ensure_writable(skb, skb->len)) 277 277 return 0; 278 278 279 279 if (cp->app_data == (void *) IP_VS_FTP_PASV) { ··· 439 439 return 1; 440 440 441 441 /* Linear packets are much easier to deal with. */ 442 - if (!skb_make_writable(skb, skb->len)) 442 + if (skb_ensure_writable(skb, skb->len)) 443 443 return 0; 444 444 445 445 data = data_start = ip_vs_ftp_data_ptr(skb, ipvsh);
+2 -2
net/netfilter/ipvs/ip_vs_proto_sctp.c
··· 101 101 #endif 102 102 103 103 /* csum_check requires unshared skb */ 104 - if (!skb_make_writable(skb, sctphoff + sizeof(*sctph))) 104 + if (skb_ensure_writable(skb, sctphoff + sizeof(*sctph))) 105 105 return 0; 106 106 107 107 if (unlikely(cp->app != NULL)) { ··· 148 148 #endif 149 149 150 150 /* csum_check requires unshared skb */ 151 - if (!skb_make_writable(skb, sctphoff + sizeof(*sctph))) 151 + if (skb_ensure_writable(skb, sctphoff + sizeof(*sctph))) 152 152 return 0; 153 153 154 154 if (unlikely(cp->app != NULL)) {
+2 -2
net/netfilter/ipvs/ip_vs_proto_tcp.c
··· 163 163 oldlen = skb->len - tcphoff; 164 164 165 165 /* csum_check requires unshared skb */ 166 - if (!skb_make_writable(skb, tcphoff+sizeof(*tcph))) 166 + if (skb_ensure_writable(skb, tcphoff + sizeof(*tcph))) 167 167 return 0; 168 168 169 169 if (unlikely(cp->app != NULL)) { ··· 241 241 oldlen = skb->len - tcphoff; 242 242 243 243 /* csum_check requires unshared skb */ 244 - if (!skb_make_writable(skb, tcphoff+sizeof(*tcph))) 244 + if (skb_ensure_writable(skb, tcphoff + sizeof(*tcph))) 245 245 return 0; 246 246 247 247 if (unlikely(cp->app != NULL)) {
+2 -2
net/netfilter/ipvs/ip_vs_proto_udp.c
··· 153 153 oldlen = skb->len - udphoff; 154 154 155 155 /* csum_check requires unshared skb */ 156 - if (!skb_make_writable(skb, udphoff+sizeof(*udph))) 156 + if (skb_ensure_writable(skb, udphoff + sizeof(*udph))) 157 157 return 0; 158 158 159 159 if (unlikely(cp->app != NULL)) { ··· 236 236 oldlen = skb->len - udphoff; 237 237 238 238 /* csum_check requires unshared skb */ 239 - if (!skb_make_writable(skb, udphoff+sizeof(*udph))) 239 + if (skb_ensure_writable(skb, udphoff + sizeof(*udph))) 240 240 return 0; 241 241 242 242 if (unlikely(cp->app != NULL)) {
+133 -22
net/netfilter/ipvs/ip_vs_xmit.c
··· 40 40 #include <net/ipv6.h> 41 41 #include <net/ip6_route.h> 42 42 #include <net/ip_tunnels.h> 43 + #include <net/ip6_checksum.h> 43 44 #include <net/addrconf.h> 44 45 #include <linux/icmpv6.h> 45 46 #include <linux/netfilter.h> ··· 280 279 } 281 280 282 281 /* don't propagate ttl change to cloned packets */ 283 - if (!skb_make_writable(skb, sizeof(struct ipv6hdr))) 282 + if (skb_ensure_writable(skb, sizeof(struct ipv6hdr))) 284 283 return false; 285 284 286 285 ipv6_hdr(skb)->hop_limit--; ··· 295 294 } 296 295 297 296 /* don't propagate ttl change to cloned packets */ 298 - if (!skb_make_writable(skb, sizeof(struct iphdr))) 297 + if (skb_ensure_writable(skb, sizeof(struct iphdr))) 299 298 return false; 300 299 301 300 /* Decrease ttl */ ··· 386 385 mtu = dst_mtu(&rt->dst) - sizeof(struct iphdr); 387 386 if (!dest) 388 387 goto err_put; 389 - if (dest->tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) 388 + if (dest->tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) { 390 389 mtu -= sizeof(struct udphdr) + sizeof(struct guehdr); 390 + if ((dest->tun_flags & 391 + IP_VS_TUNNEL_ENCAP_FLAG_REMCSUM) && 392 + skb->ip_summed == CHECKSUM_PARTIAL) 393 + mtu -= GUE_PLEN_REMCSUM + GUE_LEN_PRIV; 394 + } 391 395 if (mtu < 68) { 392 396 IP_VS_DBG_RL("%s(): mtu less than 68\n", __func__); 393 397 goto err_put; ··· 546 540 mtu = dst_mtu(&rt->dst) - sizeof(struct ipv6hdr); 547 541 if (!dest) 548 542 goto err_put; 549 - if (dest->tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) 543 + if (dest->tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) { 550 544 mtu -= sizeof(struct udphdr) + sizeof(struct guehdr); 545 + if ((dest->tun_flags & 546 + IP_VS_TUNNEL_ENCAP_FLAG_REMCSUM) && 547 + skb->ip_summed == CHECKSUM_PARTIAL) 548 + mtu -= GUE_PLEN_REMCSUM + GUE_LEN_PRIV; 549 + } 551 550 if (mtu < IPV6_MIN_MTU) { 552 551 IP_VS_DBG_RL("%s(): mtu less than %d\n", __func__, 553 552 IPV6_MIN_MTU); ··· 807 796 } 808 797 809 798 /* copy-on-write the packet before mangling it */ 810 - if (!skb_make_writable(skb, sizeof(struct iphdr))) 799 + if (skb_ensure_writable(skb, sizeof(struct iphdr))) 811 800 goto tx_error; 812 801 813 802 if (skb_cow(skb, rt->dst.dev->hard_header_len)) ··· 896 885 } 897 886 898 887 /* copy-on-write the packet before mangling it */ 899 - if (!skb_make_writable(skb, sizeof(struct ipv6hdr))) 888 + if (skb_ensure_writable(skb, sizeof(struct ipv6hdr))) 900 889 goto tx_error; 901 890 902 891 if (skb_cow(skb, rt->dst.dev->hard_header_len)) ··· 1017 1006 __be16 sport = udp_flow_src_port(net, skb, 0, 0, false); 1018 1007 struct udphdr *udph; /* Our new UDP header */ 1019 1008 struct guehdr *gueh; /* Our new GUE header */ 1009 + size_t hdrlen, optlen = 0; 1010 + void *data; 1011 + bool need_priv = false; 1020 1012 1021 - skb_push(skb, sizeof(struct guehdr)); 1013 + if ((cp->dest->tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_REMCSUM) && 1014 + skb->ip_summed == CHECKSUM_PARTIAL) { 1015 + optlen += GUE_PLEN_REMCSUM + GUE_LEN_PRIV; 1016 + need_priv = true; 1017 + } 1018 + 1019 + hdrlen = sizeof(struct guehdr) + optlen; 1020 + 1021 + skb_push(skb, hdrlen); 1022 1022 1023 1023 gueh = (struct guehdr *)skb->data; 1024 1024 1025 1025 gueh->control = 0; 1026 1026 gueh->version = 0; 1027 - gueh->hlen = 0; 1027 + gueh->hlen = optlen >> 2; 1028 1028 gueh->flags = 0; 1029 1029 gueh->proto_ctype = *next_protocol; 1030 + 1031 + data = &gueh[1]; 1032 + 1033 + if (need_priv) { 1034 + __be32 *flags = data; 1035 + u16 csum_start = skb_checksum_start_offset(skb); 1036 + __be16 *pd; 1037 + 1038 + gueh->flags |= GUE_FLAG_PRIV; 1039 + *flags = 0; 1040 + data += GUE_LEN_PRIV; 1041 + 1042 + if (csum_start < hdrlen) 1043 + return -EINVAL; 1044 + 1045 + csum_start -= hdrlen; 1046 + pd = data; 1047 + pd[0] = htons(csum_start); 1048 + pd[1] = htons(csum_start + skb->csum_offset); 1049 + 1050 + if (!skb_is_gso(skb)) { 1051 + skb->ip_summed = CHECKSUM_NONE; 1052 + skb->encapsulation = 0; 1053 + } 1054 + 1055 + *flags |= GUE_PFLAG_REMCSUM; 1056 + data += GUE_PLEN_REMCSUM; 1057 + } 1030 1058 1031 1059 skb_push(skb, sizeof(struct udphdr)); 1032 1060 skb_reset_transport_header(skb); ··· 1120 1070 unsigned int max_headroom; /* The extra header space needed */ 1121 1071 int ret, local; 1122 1072 int tun_type, gso_type; 1073 + int tun_flags; 1123 1074 1124 1075 EnterFunction(10); 1125 1076 ··· 1143 1092 max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(struct iphdr); 1144 1093 1145 1094 tun_type = cp->dest->tun_type; 1095 + tun_flags = cp->dest->tun_flags; 1146 1096 1147 - if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) 1148 - max_headroom += sizeof(struct udphdr) + sizeof(struct guehdr); 1097 + if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) { 1098 + size_t gue_hdrlen, gue_optlen = 0; 1099 + 1100 + if ((tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_REMCSUM) && 1101 + skb->ip_summed == CHECKSUM_PARTIAL) { 1102 + gue_optlen += GUE_PLEN_REMCSUM + GUE_LEN_PRIV; 1103 + } 1104 + gue_hdrlen = sizeof(struct guehdr) + gue_optlen; 1105 + 1106 + max_headroom += sizeof(struct udphdr) + gue_hdrlen; 1107 + } 1149 1108 1150 1109 /* We only care about the df field if sysctl_pmtu_disc(ipvs) is set */ 1151 1110 dfp = sysctl_pmtu_disc(ipvs) ? &df : NULL; ··· 1166 1105 goto tx_error; 1167 1106 1168 1107 gso_type = __tun_gso_type_mask(AF_INET, cp->af); 1169 - if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) 1170 - gso_type |= SKB_GSO_UDP_TUNNEL; 1108 + if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) { 1109 + if ((tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_CSUM) || 1110 + (tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_REMCSUM)) 1111 + gso_type |= SKB_GSO_UDP_TUNNEL_CSUM; 1112 + else 1113 + gso_type |= SKB_GSO_UDP_TUNNEL; 1114 + if ((tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_REMCSUM) && 1115 + skb->ip_summed == CHECKSUM_PARTIAL) { 1116 + gso_type |= SKB_GSO_TUNNEL_REMCSUM; 1117 + } 1118 + } 1171 1119 1172 1120 if (iptunnel_handle_offloads(skb, gso_type)) 1173 1121 goto tx_error; ··· 1185 1115 1186 1116 skb_set_inner_ipproto(skb, next_protocol); 1187 1117 1188 - if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) 1189 - ipvs_gue_encap(net, skb, cp, &next_protocol); 1118 + if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) { 1119 + bool check = false; 1120 + 1121 + if (ipvs_gue_encap(net, skb, cp, &next_protocol)) 1122 + goto tx_error; 1123 + 1124 + if ((tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_CSUM) || 1125 + (tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_REMCSUM)) 1126 + check = true; 1127 + 1128 + udp_set_csum(!check, skb, saddr, cp->daddr.ip, skb->len); 1129 + } 1130 + 1190 1131 1191 1132 skb_push(skb, sizeof(struct iphdr)); 1192 1133 skb_reset_network_header(skb); ··· 1255 1174 unsigned int max_headroom; /* The extra header space needed */ 1256 1175 int ret, local; 1257 1176 int tun_type, gso_type; 1177 + int tun_flags; 1258 1178 1259 1179 EnterFunction(10); 1260 1180 ··· 1279 1197 max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(struct ipv6hdr); 1280 1198 1281 1199 tun_type = cp->dest->tun_type; 1200 + tun_flags = cp->dest->tun_flags; 1282 1201 1283 - if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) 1284 - max_headroom += sizeof(struct udphdr) + sizeof(struct guehdr); 1202 + if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) { 1203 + size_t gue_hdrlen, gue_optlen = 0; 1204 + 1205 + if ((tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_REMCSUM) && 1206 + skb->ip_summed == CHECKSUM_PARTIAL) { 1207 + gue_optlen += GUE_PLEN_REMCSUM + GUE_LEN_PRIV; 1208 + } 1209 + gue_hdrlen = sizeof(struct guehdr) + gue_optlen; 1210 + 1211 + max_headroom += sizeof(struct udphdr) + gue_hdrlen; 1212 + } 1285 1213 1286 1214 skb = ip_vs_prepare_tunneled_skb(skb, cp->af, max_headroom, 1287 1215 &next_protocol, &payload_len, ··· 1300 1208 goto tx_error; 1301 1209 1302 1210 gso_type = __tun_gso_type_mask(AF_INET6, cp->af); 1303 - if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) 1304 - gso_type |= SKB_GSO_UDP_TUNNEL; 1211 + if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) { 1212 + if ((tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_CSUM) || 1213 + (tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_REMCSUM)) 1214 + gso_type |= SKB_GSO_UDP_TUNNEL_CSUM; 1215 + else 1216 + gso_type |= SKB_GSO_UDP_TUNNEL; 1217 + if ((tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_REMCSUM) && 1218 + skb->ip_summed == CHECKSUM_PARTIAL) { 1219 + gso_type |= SKB_GSO_TUNNEL_REMCSUM; 1220 + } 1221 + } 1305 1222 1306 1223 if (iptunnel_handle_offloads(skb, gso_type)) 1307 1224 goto tx_error; ··· 1319 1218 1320 1219 skb_set_inner_ipproto(skb, next_protocol); 1321 1220 1322 - if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) 1323 - ipvs_gue_encap(net, skb, cp, &next_protocol); 1221 + if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) { 1222 + bool check = false; 1223 + 1224 + if (ipvs_gue_encap(net, skb, cp, &next_protocol)) 1225 + goto tx_error; 1226 + 1227 + if ((tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_CSUM) || 1228 + (tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_REMCSUM)) 1229 + check = true; 1230 + 1231 + udp6_set_csum(!check, skb, &saddr, &cp->daddr.in6, skb->len); 1232 + } 1324 1233 1325 1234 skb_push(skb, sizeof(struct ipv6hdr)); 1326 1235 skb_reset_network_header(skb); ··· 1515 1404 } 1516 1405 1517 1406 /* copy-on-write the packet before mangling it */ 1518 - if (!skb_make_writable(skb, offset)) 1407 + if (skb_ensure_writable(skb, offset)) 1519 1408 goto tx_error; 1520 1409 1521 1410 if (skb_cow(skb, rt->dst.dev->hard_header_len)) ··· 1604 1493 } 1605 1494 1606 1495 /* copy-on-write the packet before mangling it */ 1607 - if (!skb_make_writable(skb, offset)) 1496 + if (skb_ensure_writable(skb, offset)) 1608 1497 goto tx_error; 1609 1498 1610 1499 if (skb_cow(skb, rt->dst.dev->hard_header_len))
+1 -1
net/netfilter/nf_conntrack_proto_sctp.c
··· 339 339 if (state->hook == NF_INET_PRE_ROUTING && 340 340 state->net->ct.sysctl_checksum && 341 341 skb->ip_summed == CHECKSUM_NONE) { 342 - if (!skb_make_writable(skb, dataoff + sizeof(struct sctphdr))) { 342 + if (skb_ensure_writable(skb, dataoff + sizeof(*sh))) { 343 343 logmsg = "nf_ct_sctp: failed to read header "; 344 344 goto out_invalid; 345 345 }
+2 -2
net/netfilter/nf_conntrack_seqadj.c
··· 126 126 optoff = protoff + sizeof(struct tcphdr); 127 127 optend = protoff + tcph->doff * 4; 128 128 129 - if (!skb_make_writable(skb, optend)) 129 + if (skb_ensure_writable(skb, optend)) 130 130 return 0; 131 131 132 132 tcph = (void *)skb->data + protoff; ··· 176 176 this_way = &seqadj->seq[dir]; 177 177 other_way = &seqadj->seq[!dir]; 178 178 179 - if (!skb_make_writable(skb, protoff + sizeof(*tcph))) 179 + if (skb_ensure_writable(skb, protoff + sizeof(*tcph))) 180 180 return 0; 181 181 182 182 tcph = (void *)skb->data + protoff;
-1
net/netfilter/nf_flow_table_core.c
··· 53 53 ft->dst_port = ctt->dst.u.tcp.port; 54 54 55 55 ft->iifidx = other_dst->dev->ifindex; 56 - ft->oifidx = dst->dev->ifindex; 57 56 ft->dst_cache = dst; 58 57 } 59 58
+2 -2
net/netfilter/nf_nat_helper.c
··· 98 98 struct tcphdr *tcph; 99 99 int oldlen, datalen; 100 100 101 - if (!skb_make_writable(skb, skb->len)) 101 + if (skb_ensure_writable(skb, skb->len)) 102 102 return false; 103 103 104 104 if (rep_len > match_len && ··· 148 148 struct udphdr *udph; 149 149 int datalen, oldlen; 150 150 151 - if (!skb_make_writable(skb, skb->len)) 151 + if (skb_ensure_writable(skb, skb->len)) 152 152 return false; 153 153 154 154 if (rep_len > match_len &&
+12 -12
net/netfilter/nf_nat_proto.c
··· 73 73 struct udphdr *hdr; 74 74 bool do_csum; 75 75 76 - if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) 76 + if (skb_ensure_writable(skb, hdroff + sizeof(*hdr))) 77 77 return false; 78 78 79 79 hdr = (struct udphdr *)(skb->data + hdroff); ··· 91 91 #ifdef CONFIG_NF_CT_PROTO_UDPLITE 92 92 struct udphdr *hdr; 93 93 94 - if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) 94 + if (skb_ensure_writable(skb, hdroff + sizeof(*hdr))) 95 95 return false; 96 96 97 97 hdr = (struct udphdr *)(skb->data + hdroff); ··· 117 117 if (skb->len >= hdroff + sizeof(*hdr)) 118 118 hdrsize = sizeof(*hdr); 119 119 120 - if (!skb_make_writable(skb, hdroff + hdrsize)) 120 + if (skb_ensure_writable(skb, hdroff + hdrsize)) 121 121 return false; 122 122 123 123 hdr = (struct sctphdr *)(skb->data + hdroff); ··· 158 158 if (skb->len >= hdroff + sizeof(struct tcphdr)) 159 159 hdrsize = sizeof(struct tcphdr); 160 160 161 - if (!skb_make_writable(skb, hdroff + hdrsize)) 161 + if (skb_ensure_writable(skb, hdroff + hdrsize)) 162 162 return false; 163 163 164 164 hdr = (struct tcphdr *)(skb->data + hdroff); ··· 198 198 if (skb->len >= hdroff + sizeof(struct dccp_hdr)) 199 199 hdrsize = sizeof(struct dccp_hdr); 200 200 201 - if (!skb_make_writable(skb, hdroff + hdrsize)) 201 + if (skb_ensure_writable(skb, hdroff + hdrsize)) 202 202 return false; 203 203 204 204 hdr = (struct dccp_hdr *)(skb->data + hdroff); ··· 232 232 { 233 233 struct icmphdr *hdr; 234 234 235 - if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) 235 + if (skb_ensure_writable(skb, hdroff + sizeof(*hdr))) 236 236 return false; 237 237 238 238 hdr = (struct icmphdr *)(skb->data + hdroff); ··· 250 250 { 251 251 struct icmp6hdr *hdr; 252 252 253 - if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) 253 + if (skb_ensure_writable(skb, hdroff + sizeof(*hdr))) 254 254 return false; 255 255 256 256 hdr = (struct icmp6hdr *)(skb->data + hdroff); ··· 278 278 279 279 /* pgreh includes two optional 32bit fields which are not required 280 280 * to be there. That's where the magic '8' comes from */ 281 - if (!skb_make_writable(skb, hdroff + sizeof(*pgreh) - 8)) 281 + if (skb_ensure_writable(skb, hdroff + sizeof(*pgreh) - 8)) 282 282 return false; 283 283 284 284 greh = (void *)skb->data + hdroff; ··· 350 350 struct iphdr *iph; 351 351 unsigned int hdroff; 352 352 353 - if (!skb_make_writable(skb, iphdroff + sizeof(*iph))) 353 + if (skb_ensure_writable(skb, iphdroff + sizeof(*iph))) 354 354 return false; 355 355 356 356 iph = (void *)skb->data + iphdroff; ··· 381 381 int hdroff; 382 382 u8 nexthdr; 383 383 384 - if (!skb_make_writable(skb, iphdroff + sizeof(*ipv6h))) 384 + if (skb_ensure_writable(skb, iphdroff + sizeof(*ipv6h))) 385 385 return false; 386 386 387 387 ipv6h = (void *)skb->data + iphdroff; ··· 565 565 566 566 WARN_ON(ctinfo != IP_CT_RELATED && ctinfo != IP_CT_RELATED_REPLY); 567 567 568 - if (!skb_make_writable(skb, hdrlen + sizeof(*inside))) 568 + if (skb_ensure_writable(skb, hdrlen + sizeof(*inside))) 569 569 return 0; 570 570 if (nf_ip_checksum(skb, hooknum, hdrlen, 0)) 571 571 return 0; ··· 787 787 788 788 WARN_ON(ctinfo != IP_CT_RELATED && ctinfo != IP_CT_RELATED_REPLY); 789 789 790 - if (!skb_make_writable(skb, hdrlen + sizeof(*inside))) 790 + if (skb_ensure_writable(skb, hdrlen + sizeof(*inside))) 791 791 return 0; 792 792 if (nf_ip6_checksum(skb, hooknum, hdrlen, IPPROTO_ICMPV6)) 793 793 return 0;
+1 -1
net/netfilter/nf_nat_sip.c
··· 285 285 if (dir == IP_CT_DIR_REPLY && ct_sip_info->forced_dport) { 286 286 struct udphdr *uh; 287 287 288 - if (!skb_make_writable(skb, skb->len)) { 288 + if (skb_ensure_writable(skb, skb->len)) { 289 289 nf_ct_helper_log(skb, ct, "cannot mangle packet"); 290 290 return NF_DROP; 291 291 }
+1 -1
net/netfilter/nf_synproxy_core.c
··· 196 196 optoff = protoff + sizeof(struct tcphdr); 197 197 optend = protoff + th->doff * 4; 198 198 199 - if (!skb_make_writable(skb, optend)) 199 + if (skb_ensure_writable(skb, optend)) 200 200 return 0; 201 201 202 202 while (optoff < optend) {
+10 -16
net/netfilter/nf_tables_api.c
··· 1449 1449 return newstats; 1450 1450 } 1451 1451 1452 - static void nft_chain_stats_replace(struct net *net, 1453 - struct nft_base_chain *chain, 1454 - struct nft_stats __percpu *newstats) 1452 + static void nft_chain_stats_replace(struct nft_trans *trans) 1455 1453 { 1456 - struct nft_stats __percpu *oldstats; 1454 + struct nft_base_chain *chain = nft_base_chain(trans->ctx.chain); 1457 1455 1458 - if (newstats == NULL) 1456 + if (!nft_trans_chain_stats(trans)) 1459 1457 return; 1460 1458 1461 - if (rcu_access_pointer(chain->stats)) { 1462 - oldstats = rcu_dereference_protected(chain->stats, 1463 - lockdep_commit_lock_is_held(net)); 1464 - rcu_assign_pointer(chain->stats, newstats); 1465 - synchronize_rcu(); 1466 - free_percpu(oldstats); 1467 - } else { 1468 - rcu_assign_pointer(chain->stats, newstats); 1459 + rcu_swap_protected(chain->stats, nft_trans_chain_stats(trans), 1460 + lockdep_commit_lock_is_held(trans->ctx.net)); 1461 + 1462 + if (!nft_trans_chain_stats(trans)) 1469 1463 static_branch_inc(&nft_counters_enabled); 1470 - } 1471 1464 } 1472 1465 1473 1466 static void nf_tables_chain_free_chain_rules(struct nft_chain *chain) ··· 6355 6362 if (!nft_is_base_chain(trans->ctx.chain)) 6356 6363 return; 6357 6364 6365 + nft_chain_stats_replace(trans); 6366 + 6358 6367 basechain = nft_base_chain(trans->ctx.chain); 6359 - nft_chain_stats_replace(trans->ctx.net, basechain, 6360 - nft_trans_chain_stats(trans)); 6361 6368 6362 6369 switch (nft_trans_chain_policy(trans)) { 6363 6370 case NF_DROP: ··· 6374 6381 nf_tables_table_destroy(&trans->ctx); 6375 6382 break; 6376 6383 case NFT_MSG_NEWCHAIN: 6384 + free_percpu(nft_trans_chain_stats(trans)); 6377 6385 kfree(nft_trans_chain_name(trans)); 6378 6386 break; 6379 6387 case NFT_MSG_DELCHAIN:
+2 -1
net/netfilter/nft_exthdr.c
··· 156 156 if (i + optl > tcphdr_len || priv->len + priv->offset > optl) 157 157 return; 158 158 159 - if (!skb_make_writable(pkt->skb, pkt->xt.thoff + i + priv->len)) 159 + if (skb_ensure_writable(pkt->skb, 160 + pkt->xt.thoff + i + priv->len)) 160 161 return; 161 162 162 163 tcph = nft_tcp_header_pointer(pkt, sizeof(buff), buff,
+3 -3
net/netfilter/nft_payload.c
··· 243 243 tsum)); 244 244 } 245 245 246 - if (!skb_make_writable(skb, l4csum_offset + sizeof(sum)) || 246 + if (skb_ensure_writable(skb, l4csum_offset + sizeof(sum)) || 247 247 skb_store_bits(skb, l4csum_offset, &sum, sizeof(sum)) < 0) 248 248 return -1; 249 249 ··· 259 259 return -1; 260 260 261 261 nft_csum_replace(&sum, fsum, tsum); 262 - if (!skb_make_writable(skb, csum_offset + sizeof(sum)) || 262 + if (skb_ensure_writable(skb, csum_offset + sizeof(sum)) || 263 263 skb_store_bits(skb, csum_offset, &sum, sizeof(sum)) < 0) 264 264 return -1; 265 265 ··· 312 312 goto err; 313 313 } 314 314 315 - if (!skb_make_writable(skb, max(offset + priv->len, 0)) || 315 + if (skb_ensure_writable(skb, max(offset + priv->len, 0)) || 316 316 skb_store_bits(skb, offset, src, priv->len) < 0) 317 317 goto err; 318 318
+4 -4
net/netfilter/xt_DSCP.c
··· 34 34 u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; 35 35 36 36 if (dscp != dinfo->dscp) { 37 - if (!skb_make_writable(skb, sizeof(struct iphdr))) 37 + if (skb_ensure_writable(skb, sizeof(struct iphdr))) 38 38 return NF_DROP; 39 39 40 40 ipv4_change_dsfield(ip_hdr(skb), ··· 52 52 u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; 53 53 54 54 if (dscp != dinfo->dscp) { 55 - if (!skb_make_writable(skb, sizeof(struct ipv6hdr))) 55 + if (skb_ensure_writable(skb, sizeof(struct ipv6hdr))) 56 56 return NF_DROP; 57 57 58 58 ipv6_change_dsfield(ipv6_hdr(skb), ··· 82 82 nv = (orig & ~info->tos_mask) ^ info->tos_value; 83 83 84 84 if (orig != nv) { 85 - if (!skb_make_writable(skb, sizeof(struct iphdr))) 85 + if (skb_ensure_writable(skb, sizeof(struct iphdr))) 86 86 return NF_DROP; 87 87 iph = ip_hdr(skb); 88 88 ipv4_change_dsfield(iph, 0, nv); ··· 102 102 nv = (orig & ~info->tos_mask) ^ info->tos_value; 103 103 104 104 if (orig != nv) { 105 - if (!skb_make_writable(skb, sizeof(struct iphdr))) 105 + if (skb_ensure_writable(skb, sizeof(struct iphdr))) 106 106 return NF_DROP; 107 107 iph = ipv6_hdr(skb); 108 108 ipv6_change_dsfield(iph, 0, nv);
+2 -2
net/netfilter/xt_HL.c
··· 32 32 const struct ipt_TTL_info *info = par->targinfo; 33 33 int new_ttl; 34 34 35 - if (!skb_make_writable(skb, skb->len)) 35 + if (skb_ensure_writable(skb, sizeof(*iph))) 36 36 return NF_DROP; 37 37 38 38 iph = ip_hdr(skb); ··· 72 72 const struct ip6t_HL_info *info = par->targinfo; 73 73 int new_hl; 74 74 75 - if (!skb_make_writable(skb, skb->len)) 75 + if (skb_ensure_writable(skb, sizeof(*ip6h))) 76 76 return NF_DROP; 77 77 78 78 ip6h = ipv6_hdr(skb);
+1 -1
net/netfilter/xt_TCPMSS.c
··· 89 89 if (par->fragoff != 0) 90 90 return 0; 91 91 92 - if (!skb_make_writable(skb, skb->len)) 92 + if (skb_ensure_writable(skb, skb->len)) 93 93 return -1; 94 94 95 95 len = skb->len - tcphoff;
+14 -16
net/netfilter/xt_TCPOPTSTRIP.c
··· 31 31 static unsigned int 32 32 tcpoptstrip_mangle_packet(struct sk_buff *skb, 33 33 const struct xt_action_param *par, 34 - unsigned int tcphoff, unsigned int minlen) 34 + unsigned int tcphoff) 35 35 { 36 36 const struct xt_tcpoptstrip_target_info *info = par->targinfo; 37 + struct tcphdr *tcph, _th; 37 38 unsigned int optl, i, j; 38 - struct tcphdr *tcph; 39 39 u_int16_t n, o; 40 40 u_int8_t *opt; 41 - int len, tcp_hdrlen; 41 + int tcp_hdrlen; 42 42 43 43 /* This is a fragment, no TCP header is available */ 44 44 if (par->fragoff != 0) 45 45 return XT_CONTINUE; 46 46 47 - if (!skb_make_writable(skb, skb->len)) 47 + tcph = skb_header_pointer(skb, tcphoff, sizeof(_th), &_th); 48 + if (!tcph) 48 49 return NF_DROP; 49 50 50 - len = skb->len - tcphoff; 51 - if (len < (int)sizeof(struct tcphdr)) 52 - return NF_DROP; 53 - 54 - tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); 55 51 tcp_hdrlen = tcph->doff * 4; 56 - 57 - if (len < tcp_hdrlen) 52 + if (tcp_hdrlen < sizeof(struct tcphdr)) 58 53 return NF_DROP; 59 54 60 - opt = (u_int8_t *)tcph; 55 + if (skb_ensure_writable(skb, tcphoff + tcp_hdrlen)) 56 + return NF_DROP; 57 + 58 + /* must reload tcph, might have been moved */ 59 + tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); 60 + opt = (u8 *)tcph; 61 61 62 62 /* 63 63 * Walk through all TCP options - if we find some option to remove, ··· 91 91 static unsigned int 92 92 tcpoptstrip_tg4(struct sk_buff *skb, const struct xt_action_param *par) 93 93 { 94 - return tcpoptstrip_mangle_packet(skb, par, ip_hdrlen(skb), 95 - sizeof(struct iphdr) + sizeof(struct tcphdr)); 94 + return tcpoptstrip_mangle_packet(skb, par, ip_hdrlen(skb)); 96 95 } 97 96 98 97 #if IS_ENABLED(CONFIG_IP6_NF_MANGLE) ··· 108 109 if (tcphoff < 0) 109 110 return NF_DROP; 110 111 111 - return tcpoptstrip_mangle_packet(skb, par, tcphoff, 112 - sizeof(*ipv6h) + sizeof(struct tcphdr)); 112 + return tcpoptstrip_mangle_packet(skb, par, tcphoff); 113 113 } 114 114 #endif 115 115
+20 -3
net/netfilter/xt_owner.c
··· 91 91 } 92 92 93 93 if (info->match & XT_OWNER_GID) { 94 + unsigned int i, match = false; 94 95 kgid_t gid_min = make_kgid(net->user_ns, info->gid_min); 95 96 kgid_t gid_max = make_kgid(net->user_ns, info->gid_max); 96 - if ((gid_gte(filp->f_cred->fsgid, gid_min) && 97 - gid_lte(filp->f_cred->fsgid, gid_max)) ^ 98 - !(info->invert & XT_OWNER_GID)) 97 + struct group_info *gi = filp->f_cred->group_info; 98 + 99 + if (gid_gte(filp->f_cred->fsgid, gid_min) && 100 + gid_lte(filp->f_cred->fsgid, gid_max)) 101 + match = true; 102 + 103 + if (!match && (info->match & XT_OWNER_SUPPL_GROUPS) && gi) { 104 + for (i = 0; i < gi->ngroups; ++i) { 105 + kgid_t group = gi->gid[i]; 106 + 107 + if (gid_gte(group, gid_min) && 108 + gid_lte(group, gid_max)) { 109 + match = true; 110 + break; 111 + } 112 + } 113 + } 114 + 115 + if (match ^ !(info->invert & XT_OWNER_GID)) 99 116 return false; 100 117 } 101 118