]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
Merge tag 'ipvs-for-v4.10' of https://git.kernel.org/pub/scm/linux/kernel/git/horms...
authorPablo Neira Ayuso <pablo@netfilter.org>
Sun, 4 Dec 2016 19:46:16 +0000 (20:46 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sun, 4 Dec 2016 19:46:16 +0000 (20:46 +0100)
Simon Horman says:

====================
IPVS Updates for v4.10

please consider these enhancements to the IPVS for v4.10.

* Decrement the IP ttl in all the modes in order to prevent infinite
  route loops. Thanks to Dwip Banerjee.
* Use IS_ERR_OR_NULL macro. Clean-up from Gao Feng.
====================

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/ipvs/ip_vs_xmit.c

index 038c2ba0ae0fa5877d3ed63e8c7ade908a45261b..3d02b0c1354766c60e08a42fe66926b80dd2680f 100644 (file)
@@ -3260,7 +3260,7 @@ static int ip_vs_genl_dump_dests(struct sk_buff *skb,
 
 
        svc = ip_vs_genl_find_service(ipvs, attrs[IPVS_CMD_ATTR_SERVICE]);
-       if (IS_ERR(svc) || svc == NULL)
+       if (IS_ERR_OR_NULL(svc))
                goto out_err;
 
        /* Dump the destinations */
index 01d3d894de4630b345084c8e0079a235923974b5..4e1a98fcc8c3faa3fd037cc0516fd8a3108ab2a9 100644 (file)
@@ -254,6 +254,54 @@ static inline bool ensure_mtu_is_adequate(struct netns_ipvs *ipvs, int skb_af,
        return true;
 }
 
+static inline bool decrement_ttl(struct netns_ipvs *ipvs,
+                                int skb_af,
+                                struct sk_buff *skb)
+{
+       struct net *net = ipvs->net;
+
+#ifdef CONFIG_IP_VS_IPV6
+       if (skb_af == AF_INET6) {
+               struct dst_entry *dst = skb_dst(skb);
+
+               /* check and decrement ttl */
+               if (ipv6_hdr(skb)->hop_limit <= 1) {
+                       /* Force OUTPUT device used as source address */
+                       skb->dev = dst->dev;
+                       icmpv6_send(skb, ICMPV6_TIME_EXCEED,
+                                   ICMPV6_EXC_HOPLIMIT, 0);
+                       __IP6_INC_STATS(net, ip6_dst_idev(dst),
+                                       IPSTATS_MIB_INHDRERRORS);
+
+                       return false;
+               }
+
+               /* don't propagate ttl change to cloned packets */
+               if (!skb_make_writable(skb, sizeof(struct ipv6hdr)))
+                       return false;
+
+               ipv6_hdr(skb)->hop_limit--;
+       } else
+#endif
+       {
+               if (ip_hdr(skb)->ttl <= 1) {
+                       /* Tell the sender its packet died... */
+                       __IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS);
+                       icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
+                       return false;
+               }
+
+               /* don't propagate ttl change to cloned packets */
+               if (!skb_make_writable(skb, sizeof(struct iphdr)))
+                       return false;
+
+               /* Decrease ttl */
+               ip_decrease_ttl(ip_hdr(skb));
+       }
+
+       return true;
+}
+
 /* Get route to destination or remote server */
 static int
 __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
@@ -326,6 +374,9 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
                return local;
        }
 
+       if (!decrement_ttl(ipvs, skb_af, skb))
+               goto err_put;
+
        if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL))) {
                mtu = dst_mtu(&rt->dst);
        } else {
@@ -473,6 +524,9 @@ __ip_vs_get_out_rt_v6(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
                return local;
        }
 
+       if (!decrement_ttl(ipvs, skb_af, skb))
+               goto err_put;
+
        /* MTU checking */
        if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL)))
                mtu = dst_mtu(&rt->dst);