[kernel/f18] Fix ipv6 sit panic with packet size > mtu (from Michele Baldessari) (rbhz 1015905)
Josh Boyer
jwboyer at fedoraproject.org
Mon Nov 18 15:51:26 UTC 2013
commit 741d8741147ba7b2ae7243e9c91cd53c2ba3519b
Author: Josh Boyer <jwboyer at fedoraproject.org>
Date: Mon Nov 18 10:47:47 2013 -0500
Fix ipv6 sit panic with packet size > mtu (from Michele Baldessari) (rbhz 1015905)
...fragment-outgoing-reassembled-skb-properl.patch | 39 ++
...ush-reasm-skb-through-instead-of-original.patch | 499 ++++++++++++++++++++
kernel.spec | 11 +
3 files changed, 549 insertions(+), 0 deletions(-)
---
diff --git a/0001-ip6_output-fragment-outgoing-reassembled-skb-properl.patch b/0001-ip6_output-fragment-outgoing-reassembled-skb-properl.patch
new file mode 100644
index 0000000..a19217d
--- /dev/null
+++ b/0001-ip6_output-fragment-outgoing-reassembled-skb-properl.patch
@@ -0,0 +1,39 @@
+Bugzilla: 1015905
+Upstream-status: 3.13 (should hit stable)
+
+From 90e4e23d52fd04f228eed2c3d341136c50058b37 Mon Sep 17 00:00:00 2001
+From: Jiri Pirko <jiri at resnulli.us>
+Date: Wed, 6 Nov 2013 17:52:19 +0100
+Subject: [PATCH 1/2] ip6_output: fragment outgoing reassembled skb properly
+
+If reassembled packet would fit into outdev MTU, it is not fragmented
+according the original frag size and it is send as single big packet.
+
+The second case is if skb is gso. In that case fragmentation does not happen
+according to the original frag size.
+
+This patch fixes these.
+
+Signed-off-by: Jiri Pirko <jiri at resnulli.us>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ net/ipv6/ip6_output.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
+index 5b25f85..f80f2fa 100644
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -150,7 +150,8 @@ static int ip6_finish_output2(struct sk_buff *skb)
+ static int ip6_finish_output(struct sk_buff *skb)
+ {
+ if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) ||
+- dst_allfrag(skb_dst(skb)))
++ dst_allfrag(skb_dst(skb)) ||
++ (IP6CB(skb)->frag_max_size && skb->len > IP6CB(skb)->frag_max_size))
+ return ip6_fragment(skb, ip6_finish_output2);
+ else
+ return ip6_finish_output2(skb);
+--
+1.8.3.1
+
diff --git a/0002-netfilter-push-reasm-skb-through-instead-of-original.patch b/0002-netfilter-push-reasm-skb-through-instead-of-original.patch
new file mode 100644
index 0000000..27fee51
--- /dev/null
+++ b/0002-netfilter-push-reasm-skb-through-instead-of-original.patch
@@ -0,0 +1,499 @@
+Bugzilla: 1015905
+Upstream-status: 3.13 (should hit stable)
+
+From 5c0df04613dd39fba5d2a43eaf90a2dc1dcd8899 Mon Sep 17 00:00:00 2001
+From: Jiri Pirko <jiri at resnulli.us>
+Date: Wed, 6 Nov 2013 17:52:20 +0100
+Subject: [PATCH 2/2] netfilter: push reasm skb through instead of original
+ frag skbs
+
+Pushing original fragments through causes several problems. For example
+for matching, frags may not be matched correctly. Take following
+example:
+
+<example>
+On HOSTA do:
+ip6tables -I INPUT -p icmpv6 -j DROP
+ip6tables -I INPUT -p icmpv6 -m icmp6 --icmpv6-type 128 -j ACCEPT
+
+and on HOSTB you do:
+ping6 HOSTA -s2000 (MTU is 1500)
+
+Incoming echo requests will be filtered out on HOSTA. This issue does
+not occur with smaller packets than MTU (where fragmentation does not happen)
+</example>
+
+As was discussed previously, the only correct solution seems to be to use
+reassembled skb instead of separete frags. Doing this has positive side
+effects in reducing sk_buff by one pointer (nfct_reasm) and also the reams
+dances in ipvs and conntrack can be removed.
+
+Future plan is to remove net/ipv6/netfilter/nf_conntrack_reasm.c
+entirely and use code in net/ipv6/reassembly.c instead.
+
+Signed-off-by: Jiri Pirko <jiri at resnulli.us>
+Acked-by: Julian Anastasov <ja at ssi.bg>
+Signed-off-by: Marcelo Ricardo Leitner <mleitner at redhat.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+
+Conflicts:
+ include/net/netfilter/ipv6/nf_defrag_ipv6.h
+ net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+ net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
+ net/netfilter/ipvs/ip_vs_core.c
+---
+ include/linux/skbuff.h | 32 ---------------
+ include/net/ip_vs.h | 32 +--------------
+ include/net/netfilter/ipv6/nf_defrag_ipv6.h | 5 +--
+ net/core/skbuff.c | 3 --
+ net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 54 +------------------------
+ net/ipv6/netfilter/nf_conntrack_reasm.c | 19 +--------
+ net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | 7 +++-
+ net/netfilter/ipvs/ip_vs_core.c | 55 +-------------------------
+ net/netfilter/ipvs/ip_vs_pe_sip.c | 8 +---
+ 9 files changed, 13 insertions(+), 202 deletions(-)
+
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index 6bd165b..37b4517 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -333,11 +333,6 @@ typedef unsigned int sk_buff_data_t;
+ typedef unsigned char *sk_buff_data_t;
+ #endif
+
+-#if defined(CONFIG_NF_DEFRAG_IPV4) || defined(CONFIG_NF_DEFRAG_IPV4_MODULE) || \
+- defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE)
+-#define NET_SKBUFF_NF_DEFRAG_NEEDED 1
+-#endif
+-
+ /**
+ * struct sk_buff - socket buffer
+ * @next: Next buffer in list
+@@ -370,7 +365,6 @@ typedef unsigned char *sk_buff_data_t;
+ * @protocol: Packet protocol from driver
+ * @destructor: Destruct function
+ * @nfct: Associated connection, if any
+- * @nfct_reasm: netfilter conntrack re-assembly pointer
+ * @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
+ * @skb_iif: ifindex of device we arrived on
+ * @tc_index: Traffic control index
+@@ -459,9 +453,6 @@ struct sk_buff {
+ #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+ struct nf_conntrack *nfct;
+ #endif
+-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
+- struct sk_buff *nfct_reasm;
+-#endif
+ #ifdef CONFIG_BRIDGE_NETFILTER
+ struct nf_bridge_info *nf_bridge;
+ #endif
+@@ -2603,18 +2594,6 @@ static inline void nf_conntrack_get(struct nf_conntrack *nfct)
+ atomic_inc(&nfct->use);
+ }
+ #endif
+-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
+-static inline void nf_conntrack_get_reasm(struct sk_buff *skb)
+-{
+- if (skb)
+- atomic_inc(&skb->users);
+-}
+-static inline void nf_conntrack_put_reasm(struct sk_buff *skb)
+-{
+- if (skb)
+- kfree_skb(skb);
+-}
+-#endif
+ #ifdef CONFIG_BRIDGE_NETFILTER
+ static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
+ {
+@@ -2633,10 +2612,6 @@ static inline void nf_reset(struct sk_buff *skb)
+ nf_conntrack_put(skb->nfct);
+ skb->nfct = NULL;
+ #endif
+-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
+- nf_conntrack_put_reasm(skb->nfct_reasm);
+- skb->nfct_reasm = NULL;
+-#endif
+ #ifdef CONFIG_BRIDGE_NETFILTER
+ nf_bridge_put(skb->nf_bridge);
+ skb->nf_bridge = NULL;
+@@ -2658,10 +2633,6 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src)
+ nf_conntrack_get(src->nfct);
+ dst->nfctinfo = src->nfctinfo;
+ #endif
+-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
+- dst->nfct_reasm = src->nfct_reasm;
+- nf_conntrack_get_reasm(src->nfct_reasm);
+-#endif
+ #ifdef CONFIG_BRIDGE_NETFILTER
+ dst->nf_bridge = src->nf_bridge;
+ nf_bridge_get(src->nf_bridge);
+@@ -2673,9 +2644,6 @@ static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src)
+ #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+ nf_conntrack_put(dst->nfct);
+ #endif
+-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
+- nf_conntrack_put_reasm(dst->nfct_reasm);
+-#endif
+ #ifdef CONFIG_BRIDGE_NETFILTER
+ nf_bridge_put(dst->nf_bridge);
+ #endif
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index f0d70f0..ff21521 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -109,7 +109,6 @@ extern int ip_vs_conn_tab_size;
+ struct ip_vs_iphdr {
+ __u32 len; /* IPv4 simply where L4 starts
+ IPv6 where L4 Transport Header starts */
+- __u32 thoff_reasm; /* Transport Header Offset in nfct_reasm skb */
+ __u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/
+ __s16 protocol;
+ __s32 flags;
+@@ -117,34 +116,12 @@ struct ip_vs_iphdr {
+ union nf_inet_addr daddr;
+ };
+
+-/* Dependency to module: nf_defrag_ipv6 */
+-#if defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE)
+-static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
+-{
+- return skb->nfct_reasm;
+-}
+-static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
+- int len, void *buffer,
+- const struct ip_vs_iphdr *ipvsh)
+-{
+- if (unlikely(ipvsh->fragoffs && skb_nfct_reasm(skb)))
+- return skb_header_pointer(skb_nfct_reasm(skb),
+- ipvsh->thoff_reasm, len, buffer);
+-
+- return skb_header_pointer(skb, offset, len, buffer);
+-}
+-#else
+-static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
+-{
+- return NULL;
+-}
+ static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
+ int len, void *buffer,
+ const struct ip_vs_iphdr *ipvsh)
+ {
+ return skb_header_pointer(skb, offset, len, buffer);
+ }
+-#endif
+
+ static inline void
+ ip_vs_fill_ip4hdr(const void *nh, struct ip_vs_iphdr *iphdr)
+@@ -171,19 +148,12 @@ ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr)
+ (struct ipv6hdr *)skb_network_header(skb);
+ iphdr->saddr.in6 = iph->saddr;
+ iphdr->daddr.in6 = iph->daddr;
+- /* ipv6_find_hdr() updates len, flags, thoff_reasm */
+- iphdr->thoff_reasm = 0;
++ /* ipv6_find_hdr() updates len, flags */
+ iphdr->len = 0;
+ iphdr->flags = 0;
+ iphdr->protocol = ipv6_find_hdr(skb, &iphdr->len, -1,
+ &iphdr->fragoffs,
+ &iphdr->flags);
+- /* get proto from re-assembled packet and it's offset */
+- if (skb_nfct_reasm(skb))
+- iphdr->protocol = ipv6_find_hdr(skb_nfct_reasm(skb),
+- &iphdr->thoff_reasm,
+- -1, NULL, NULL);
+-
+ } else
+ #endif
+ {
+diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
+index fd79c9a..17920d8 100644
+--- a/include/net/netfilter/ipv6/nf_defrag_ipv6.h
++++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
+@@ -6,10 +6,7 @@ extern void nf_defrag_ipv6_enable(void);
+ extern int nf_ct_frag6_init(void);
+ extern void nf_ct_frag6_cleanup(void);
+ extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user);
+-extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
+- struct net_device *in,
+- struct net_device *out,
+- int (*okfn)(struct sk_buff *));
++extern void nf_ct_frag6_consume_orig(struct sk_buff *skb);
+
+ struct inet_frags_ctl;
+
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 2c3d0f5..a75022e 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -580,9 +580,6 @@ static void skb_release_head_state(struct sk_buff *skb)
+ #if IS_ENABLED(CONFIG_NF_CONNTRACK)
+ nf_conntrack_put(skb->nfct);
+ #endif
+-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
+- nf_conntrack_put_reasm(skb->nfct_reasm);
+-#endif
+ #ifdef CONFIG_BRIDGE_NETFILTER
+ nf_bridge_put(skb->nf_bridge);
+ #endif
+diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+index c9b6a6e..97cd750 100644
+--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
++++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+@@ -172,63 +172,13 @@ out:
+ return nf_conntrack_confirm(skb);
+ }
+
+-static unsigned int __ipv6_conntrack_in(struct net *net,
+- unsigned int hooknum,
+- struct sk_buff *skb,
+- const struct net_device *in,
+- const struct net_device *out,
+- int (*okfn)(struct sk_buff *))
+-{
+- struct sk_buff *reasm = skb->nfct_reasm;
+- const struct nf_conn_help *help;
+- struct nf_conn *ct;
+- enum ip_conntrack_info ctinfo;
+-
+- /* This packet is fragmented and has reassembled packet. */
+- if (reasm) {
+- /* Reassembled packet isn't parsed yet ? */
+- if (!reasm->nfct) {
+- unsigned int ret;
+-
+- ret = nf_conntrack_in(net, PF_INET6, hooknum, reasm);
+- if (ret != NF_ACCEPT)
+- return ret;
+- }
+-
+- /* Conntrack helpers need the entire reassembled packet in the
+- * POST_ROUTING hook. In case of unconfirmed connections NAT
+- * might reassign a helper, so the entire packet is also
+- * required.
+- */
+- ct = nf_ct_get(reasm, &ctinfo);
+- if (ct != NULL && !nf_ct_is_untracked(ct)) {
+- help = nfct_help(ct);
+- if ((help && help->helper) || !nf_ct_is_confirmed(ct)) {
+- nf_conntrack_get_reasm(reasm);
+- NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, reasm,
+- (struct net_device *)in,
+- (struct net_device *)out,
+- okfn, NF_IP6_PRI_CONNTRACK + 1);
+- return NF_DROP_ERR(-ECANCELED);
+- }
+- }
+-
+- nf_conntrack_get(reasm->nfct);
+- skb->nfct = reasm->nfct;
+- skb->nfctinfo = reasm->nfctinfo;
+- return NF_ACCEPT;
+- }
+-
+- return nf_conntrack_in(net, PF_INET6, hooknum, skb);
+-}
+-
+ static unsigned int ipv6_conntrack_in(unsigned int hooknum,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+ {
+- return __ipv6_conntrack_in(dev_net(in), hooknum, skb, in, out, okfn);
++ return nf_conntrack_in(dev_net(in), PF_INET6, hooknum, skb);
+ }
+
+ static unsigned int ipv6_conntrack_local(unsigned int hooknum,
+@@ -242,7 +192,7 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum,
+ net_notice_ratelimited("ipv6_conntrack_local: packet too short\n");
+ return NF_ACCEPT;
+ }
+- return __ipv6_conntrack_in(dev_net(out), hooknum, skb, in, out, okfn);
++ return nf_conntrack_in(dev_net(out), PF_INET6, hooknum, skb);
+ }
+
+ static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {
+diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
+index dffdc1a..253566a 100644
+--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
++++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
+@@ -621,31 +621,16 @@ ret_orig:
+ return skb;
+ }
+
+-void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
+- struct net_device *in, struct net_device *out,
+- int (*okfn)(struct sk_buff *))
++void nf_ct_frag6_consume_orig(struct sk_buff *skb)
+ {
+ struct sk_buff *s, *s2;
+- unsigned int ret = 0;
+
+ for (s = NFCT_FRAG6_CB(skb)->orig; s;) {
+- nf_conntrack_put_reasm(s->nfct_reasm);
+- nf_conntrack_get_reasm(skb);
+- s->nfct_reasm = skb;
+-
+ s2 = s->next;
+ s->next = NULL;
+-
+- if (ret != -ECANCELED)
+- ret = NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, s,
+- in, out, okfn,
+- NF_IP6_PRI_CONNTRACK_DEFRAG + 1);
+- else
+- kfree_skb(s);
+-
++ consume_skb(s);
+ s = s2;
+ }
+- nf_conntrack_put_reasm(skb);
+ }
+
+ static int nf_ct_net_init(struct net *net)
+diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
+index aacd121..581dd9e 100644
+--- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
++++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
+@@ -75,8 +75,11 @@ static unsigned int ipv6_defrag(unsigned int hooknum,
+ if (reasm == skb)
+ return NF_ACCEPT;
+
+- nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in,
+- (struct net_device *)out, okfn);
++ nf_ct_frag6_consume_orig(reasm);
++
++ NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, reasm,
++ (struct net_device *) in, (struct net_device *) out,
++ okfn, NF_IP6_PRI_CONNTRACK_DEFRAG + 1);
+
+ return NF_STOLEN;
+ }
+diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
+index 4f69e83..1517b50 100644
+--- a/net/netfilter/ipvs/ip_vs_core.c
++++ b/net/netfilter/ipvs/ip_vs_core.c
+@@ -1131,12 +1131,6 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
+ ip_vs_fill_iph_skb(af, skb, &iph);
+ #ifdef CONFIG_IP_VS_IPV6
+ if (af == AF_INET6) {
+- if (!iph.fragoffs && skb_nfct_reasm(skb)) {
+- struct sk_buff *reasm = skb_nfct_reasm(skb);
+- /* Save fw mark for coming frags */
+- reasm->ipvs_property = 1;
+- reasm->mark = skb->mark;
+- }
+ if (unlikely(iph.protocol == IPPROTO_ICMPV6)) {
+ int related;
+ int verdict = ip_vs_out_icmp_v6(skb, &related,
+@@ -1606,12 +1600,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
+
+ #ifdef CONFIG_IP_VS_IPV6
+ if (af == AF_INET6) {
+- if (!iph.fragoffs && skb_nfct_reasm(skb)) {
+- struct sk_buff *reasm = skb_nfct_reasm(skb);
+- /* Save fw mark for coming frags. */
+- reasm->ipvs_property = 1;
+- reasm->mark = skb->mark;
+- }
+ if (unlikely(iph.protocol == IPPROTO_ICMPV6)) {
+ int related;
+ int verdict = ip_vs_in_icmp_v6(skb, &related, hooknum,
+@@ -1663,9 +1651,8 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
+ /* sorry, all this trouble for a no-hit :) */
+ IP_VS_DBG_PKT(12, af, pp, skb, 0,
+ "ip_vs_in: packet continues traversal as normal");
+- if (iph.fragoffs && !skb_nfct_reasm(skb)) {
++ if (iph.fragoffs) {
+ /* Fragment that couldn't be mapped to a conn entry
+- * and don't have any pointer to a reasm skb
+ * is missing module nf_defrag_ipv6
+ */
+ IP_VS_DBG_RL("Unhandled frag, load nf_defrag_ipv6\n");
+@@ -1748,38 +1735,6 @@ ip_vs_local_request4(unsigned int hooknum, struct sk_buff *skb,
+ #ifdef CONFIG_IP_VS_IPV6
+
+ /*
+- * AF_INET6 fragment handling
+- * Copy info from first fragment, to the rest of them.
+- */
+-static unsigned int
+-ip_vs_preroute_frag6(unsigned int hooknum, struct sk_buff *skb,
+- const struct net_device *in,
+- const struct net_device *out,
+- int (*okfn)(struct sk_buff *))
+-{
+- struct sk_buff *reasm = skb_nfct_reasm(skb);
+- struct net *net;
+-
+- /* Skip if not a "replay" from nf_ct_frag6_output or first fragment.
+- * ipvs_property is set when checking first fragment
+- * in ip_vs_in() and ip_vs_out().
+- */
+- if (reasm)
+- IP_VS_DBG(2, "Fragment recv prop:%d\n", reasm->ipvs_property);
+- if (!reasm || !reasm->ipvs_property)
+- return NF_ACCEPT;
+-
+- net = skb_net(skb);
+- if (!net_ipvs(net)->enable)
+- return NF_ACCEPT;
+-
+- /* Copy stored fw mark, saved in ip_vs_{in,out} */
+- skb->mark = reasm->mark;
+-
+- return NF_ACCEPT;
+-}
+-
+-/*
+ * AF_INET6 handler in NF_INET_LOCAL_IN chain
+ * Schedule and forward packets from remote clients
+ */
+@@ -1916,14 +1871,6 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
+ .priority = 100,
+ },
+ #ifdef CONFIG_IP_VS_IPV6
+- /* After mangle & nat fetch 2:nd fragment and following */
+- {
+- .hook = ip_vs_preroute_frag6,
+- .owner = THIS_MODULE,
+- .pf = NFPROTO_IPV6,
+- .hooknum = NF_INET_PRE_ROUTING,
+- .priority = NF_IP6_PRI_NAT_DST + 1,
+- },
+ /* After packet filtering, change source only for VS/NAT */
+ {
+ .hook = ip_vs_reply6,
+diff --git a/net/netfilter/ipvs/ip_vs_pe_sip.c b/net/netfilter/ipvs/ip_vs_pe_sip.c
+index 9ef22bd..bed5f70 100644
+--- a/net/netfilter/ipvs/ip_vs_pe_sip.c
++++ b/net/netfilter/ipvs/ip_vs_pe_sip.c
+@@ -65,7 +65,6 @@ static int get_callid(const char *dptr, unsigned int dataoff,
+ static int
+ ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb)
+ {
+- struct sk_buff *reasm = skb_nfct_reasm(skb);
+ struct ip_vs_iphdr iph;
+ unsigned int dataoff, datalen, matchoff, matchlen;
+ const char *dptr;
+@@ -79,15 +78,10 @@ ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb)
+ /* todo: IPv6 fragments:
+ * I think this only should be done for the first fragment. /HS
+ */
+- if (reasm) {
+- skb = reasm;
+- dataoff = iph.thoff_reasm + sizeof(struct udphdr);
+- } else
+- dataoff = iph.len + sizeof(struct udphdr);
++ dataoff = iph.len + sizeof(struct udphdr);
+
+ if (dataoff >= skb->len)
+ return -EINVAL;
+- /* todo: Check if this will mess-up the reasm skb !!! /HS */
+ retc = skb_linearize(skb);
+ if (retc < 0)
+ return retc;
+--
+1.8.3.1
+
diff --git a/kernel.spec b/kernel.spec
index ee80a92..3dad6f8 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -799,6 +799,10 @@ Patch25144: Input-evdev-fall-back-to-vmalloc-for-client-event-buffer.patch
#CVE-2013-4563 rhbz 1030015 1030017
Patch25145: ipv6-fix-headroom-calculation-in-udp6_ufo_fragment.patch
+#rhbz 1015905
+Patch25146: 0001-ip6_output-fragment-outgoing-reassembled-skb-properl.patch
+Patch25147: 0002-netfilter-push-reasm-skb-through-instead-of-original.patch
+
# END OF PATCH DEFINITIONS
%endif
@@ -1535,6 +1539,10 @@ ApplyPatch Input-evdev-fall-back-to-vmalloc-for-client-event-buffer.patch
#CVE-2013-4563 rhbz 1030015 1030017
ApplyPatch ipv6-fix-headroom-calculation-in-udp6_ufo_fragment.patch
+#rhbz 1015905
+ApplyPatch 0001-ip6_output-fragment-outgoing-reassembled-skb-properl.patch
+ApplyPatch 0002-netfilter-push-reasm-skb-through-instead-of-original.patch
+
# END OF PATCH APPLICATIONS
%endif
@@ -2376,6 +2384,9 @@ fi
# ||----w |
# || ||
%changelog
+* Mon Nov 18 2013 Josh Boyer <jwboyer at fedoraproject.org>
+- Fix ipv6 sit panic with packet size > mtu (from Michele Baldessari) (rbhz 1015905)
+
* Thu Nov 14 2013 Josh Boyer <jwboyer at fedoraproject.org>
- CVE-2013-4563: net: large udp packet over IPv6 over UFO-enabled device with TBF qdisc panic (rhbz 1030015 1030017)
More information about the scm-commits
mailing list