]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - net/openvswitch/conntrack.c
ipv4: Return EINVAL when ping_group_range sysctl doesn't map to user ns
[mirror_ubuntu-bionic-kernel.git] / net / openvswitch / conntrack.c
index b27c5c6d9cab305a58d04608f38252eea034c32e..8f04bd6e44bbfc3a021250b6c5496013bb34e699 100644 (file)
@@ -1098,6 +1098,36 @@ static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
        return 0;
 }
 
+/* Trim the skb to the length specified by the IP/IPv6 header,
+ * removing any trailing lower-layer padding. This prepares the skb
+ * for higher-layer processing that assumes skb->len excludes padding
+ * (such as nf_ip_checksum). The caller needs to pull the skb to the
+ * network header, and ensure ip_hdr/ipv6_hdr points to valid data.
+ */
+static int ovs_skb_network_trim(struct sk_buff *skb)
+{
+       unsigned int len;
+       int err;
+
+       switch (skb->protocol) {
+       case htons(ETH_P_IP):
+               len = ntohs(ip_hdr(skb)->tot_len);
+               break;
+       case htons(ETH_P_IPV6):
+               len = sizeof(struct ipv6hdr)
+                       + ntohs(ipv6_hdr(skb)->payload_len);
+               break;
+       default:
+               len = skb->len;
+       }
+
+       err = pskb_trim_rcsum(skb, len);
+       if (err)
+               kfree_skb(skb);
+
+       return err;
+}
+
 /* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
  * value if 'skb' is freed.
  */
@@ -1112,6 +1142,10 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
        nh_ofs = skb_network_offset(skb);
        skb_pull_rcsum(skb, nh_ofs);
 
+       err = ovs_skb_network_trim(skb);
+       if (err)
+               return err;
+
        if (key->ip.frag != OVS_FRAG_TYPE_NONE) {
                err = handle_fragments(net, key, info->zone.id, skb);
                if (err)