Message ID | AANLkTik5=zcsVHwLsFqMvRvoLyPdhK=1dRUny5+jqoxf@mail.gmail.com |
---|---|
State | RFC, archived |
Delegated to: | David Miller |
Headers | show |
This patch is for 2.6.25.16. 2011/3/23 Feng Gao <kernel.goter@gmail.com>: > Sorry, I will google it. > I find this problem in 2.4.35. and then I read the Latest code,maybe > it has the same problem too. > > diff -Nur skbuff.h skbuff.h.frag > --- skbuff.h 2008-08-21 02:16:14.000000000 +0800 > +++ skbuff.h.frag 2011-03-23 19:30:20.000000000 +0800 > @@ -1754,6 +1754,20 @@ > __nf_copy(dst, src); > } > > +/* This func for ip_fragment deal with RST packet */ > +static inline void nf_copy_rst(struct sk_buff *dst, const struct sk_buff *src) > +{ > +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) > + nf_conntrack_put(dst->nfct); > + nf_conntrack_put_reasm(dst->nfct_reasm); > +#endif > +#ifdef CONFIG_BRIDGE_NETFILTER > + nf_bridge_put(dst->nf_bridge); > + dst->nf_bridge = src->nf_bridge; > + nf_bridge_get(src->nf_bridge); > +#endif > +} > + > #ifdef CONFIG_NETWORK_SECMARK > static inline void skb_copy_secmark(struct sk_buff *to, const struct > sk_buff *from) > { > > diff -Nur ip_output.c ip_output.c.frag > --- ip_output.c 2008-08-21 02:16:14.000000000 +0800 > +++ ip_output.c.frag 2011-03-23 19:27:57.000000000 +0800 > @@ -413,7 +413,14 @@ > #ifdef CONFIG_NET_SCHED > to->tc_index = from->tc_index; > #endif > - nf_copy(to, from); > + struct tcphdr *th = (struct tcphdr *)((char *)iph + (iph->ihl << 2)); > + if(iph->protocol == IPPROTO_TCP && th->rst){ > + /*RST packet*/ > + nf_copy_rst(to, from); > + }else{ > + /*Other packet*/ > + nf_copy(to, from); > + } > #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ > defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) > to->nf_trace = from->nf_trace; > > 2011/3/23 Eric Dumazet <eric.dumazet@gmail.com>: >> Le mercredi 23 mars 2011 à 18:49 +0800, Feng Gao a écrit : >>> Hello everyone: >>> >>> PC(A)-linux(B)-PC(C) >>> computer(linux B) with two net interface,eth0 and eth1. >>> PC(A) send syn to PC(C) though linux B. >>> then PC(C) replay a big packet with RST flag(use tcpsic or other tools). >>> >>> This RST packet(1480) come in from eth0(mtu 1500) and go out from >>> eth1(mtu 700), so this RST packet should fragment. >>> >>> BUT in tcp_packet func: if the connection has no reply packet,and >>> receive the RST packet.ip_conntrack should destroy. >>> if (!test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { >>> /* If only reply is a RST, we can consider ourselves not to >>> have an established connection: this is a fairly common >>> problem case, so we can delete the conntrack >>> immediately. --RR */ >>> if (th->rst) { >>> nf_ct_kill_acct(ct, ctinfo, skb); >>> return NF_ACCEPT; >>> } >>> } >>> >>> BUT the skb->nfct is not set NULL in func nf_ct_kill_acct. >>> so when this RST packet goto ip_fragment,ip_fragment call nf_copy, in >>> __nf_copy func >>> the fragment skb->nfct point to the destory mem. >>> dst->nfct = src->nfct; >>> nf_conntrack_get(src->nfct); >>> >>> SO finally.kfree_skb call destroy_conntrack again. this may result in >>> LINUX B kernel panic. >>> >>> >>> here is the patch,sorry ,i dont know how to use diff to generate patch. >>> :-D >>> >> >> Hi Feng >> >> Oh well, please learn how to do this. If you are able to make such >> analysis, you sure can learn how to use diff !!! >> >> What is the version of linux you use ? >> >> >> >> > -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff -Nur skbuff.h skbuff.h.frag --- skbuff.h 2008-08-21 02:16:14.000000000 +0800 +++ skbuff.h.frag 2011-03-23 19:30:20.000000000 +0800 @@ -1754,6 +1754,20 @@ __nf_copy(dst, src); } +/* This func for ip_fragment deal with RST packet */ +static inline void nf_copy_rst(struct sk_buff *dst, const struct sk_buff *src) +{ +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + nf_conntrack_put(dst->nfct); + nf_conntrack_put_reasm(dst->nfct_reasm); +#endif +#ifdef CONFIG_BRIDGE_NETFILTER + nf_bridge_put(dst->nf_bridge); + dst->nf_bridge = src->nf_bridge; + nf_bridge_get(src->nf_bridge); +#endif +} + #ifdef CONFIG_NETWORK_SECMARK static inline void skb_copy_secmark(struct sk_buff *to, const struct sk_buff *from) { diff -Nur ip_output.c ip_output.c.frag --- ip_output.c 2008-08-21 02:16:14.000000000 +0800 +++ ip_output.c.frag 2011-03-23 19:27:57.000000000 +0800 @@ -413,7 +413,14 @@ #ifdef CONFIG_NET_SCHED to->tc_index = from->tc_index; #endif - nf_copy(to, from); + struct tcphdr *th = (struct tcphdr *)((char *)iph + (iph->ihl << 2)); + if(iph->protocol == IPPROTO_TCP && th->rst){ + /*RST packet*/ + nf_copy_rst(to, from); + }else{ + /*Other packet*/ + nf_copy(to, from); + } #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) to->nf_trace = from->nf_trace;