Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 54764 Details for
Bug 81195
Kernel: Remote oops/firewall bypasses (CAN-2005-{0209,0449})
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
2.6 Compound Patch
2.6-81195.patch (text/plain), 10.94 KB, created by
Tim Yamin (RETIRED)
on 2005-03-29 07:45:49 UTC
(
hide
)
Description:
2.6 Compound Patch
Filename:
MIME Type:
Creator:
Tim Yamin (RETIRED)
Created:
2005-03-29 07:45:49 UTC
Size:
10.94 KB
patch
obsolete
># ChangeSet ># 2005/01/24 16:40:33-08:00 herbert@gondor.apana.org.au ># [IPV4/IPV6]: In ip_fragment(), reset ip_summed field on SKB sub-frags. ># ># If we forward a fragmented packet, we can have ip_summed ># set to CHECKSUM_HW or similar. This is fine for local ># protocol processing, but once if we are forwarding this ># packet we want to reset ip_summed to CHECKSUM_NONE. ># ># Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> ># Signed-off-by: David S. Miller <davem@davemloft.net> ># ># ChangeSet ># 2005/01/26 22:03:38-08:00 kaber@trash.net ># [IPV4]: Keep fragment queues private to each user. ># ># Signed-off-by: Patrick McHardy <kaber@trash.net> ># Signed-off-by: David S. Miller <davem@davemloft.net> ># >diff -Naru a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h >--- a/include/linux/netfilter_ipv4/ip_conntrack.h 2005-03-29 07:19:50 -08:00 >+++ b/include/linux/netfilter_ipv4/ip_conntrack.h 2005-03-29 07:19:50 -08:00 >@@ -262,10 +262,9 @@ > /* Fake conntrack entry for untracked connections */ > extern struct ip_conntrack ip_conntrack_untracked; > >-extern int ip_ct_no_defrag; > /* Returns new sk_buff, or NULL */ > struct sk_buff * >-ip_ct_gather_frags(struct sk_buff *skb); >+ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user); > > /* Iterate over all conntracks: if iter returns true, it's deleted. */ > extern void >diff -Naru a/include/net/ip.h b/include/net/ip.h >--- a/include/net/ip.h 2005-03-29 07:19:50 -08:00 >+++ b/include/net/ip.h 2005-03-29 07:19:50 -08:00 >@@ -286,9 +286,20 @@ > /* > * Functions provided by ip_fragment.o > */ >- >-struct sk_buff *ip_defrag(struct sk_buff *skb); >-extern void ipfrag_flush(void); >+ >+enum ip_defrag_users >+{ >+ IP_DEFRAG_LOCAL_DELIVER, >+ IP_DEFRAG_CALL_RA_CHAIN, >+ IP_DEFRAG_CONNTRACK_IN, >+ IP_DEFRAG_CONNTRACK_OUT, >+ IP_DEFRAG_NAT_OUT, >+ IP_DEFRAG_VS_IN, >+ IP_DEFRAG_VS_OUT, >+ IP_DEFRAG_VS_FWD >+}; >+ >+struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user); > extern int ip_frag_nqueues; > extern atomic_t ip_frag_mem; > >diff -Naru a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c >--- a/net/ipv4/ip_fragment.c 2005-03-29 07:19:50 -08:00 >+++ b/net/ipv4/ip_fragment.c 2005-03-29 07:19:50 -08:00 >@@ -73,6 +73,7 @@ > struct ipq { > struct ipq *next; /* linked list pointers */ > struct list_head lru_list; /* lru list member */ >+ u32 user; > u32 saddr; > u32 daddr; > u16 id; >@@ -243,13 +244,13 @@ > /* Memory limiting on fragments. Evictor trashes the oldest > * fragment queue until we are back under the threshold. > */ >-static void __ip_evictor(int threshold) >+static void ip_evictor(void) > { > struct ipq *qp; > struct list_head *tmp; > int work; > >- work = atomic_read(&ip_frag_mem) - threshold; >+ work = atomic_read(&ip_frag_mem) - sysctl_ipfrag_low_thresh; > if (work <= 0) > return; > >@@ -274,11 +275,6 @@ > } > } > >-static inline void ip_evictor(void) >-{ >- __ip_evictor(sysctl_ipfrag_low_thresh); >-} >- > /* > * Oops, a fragment queue timed out. Kill it and send an ICMP reply. > */ >@@ -325,7 +321,8 @@ > if(qp->id == qp_in->id && > qp->saddr == qp_in->saddr && > qp->daddr == qp_in->daddr && >- qp->protocol == qp_in->protocol) { >+ qp->protocol == qp_in->protocol && >+ qp->user == qp_in->user) { > atomic_inc(&qp->refcnt); > write_unlock(&ipfrag_lock); > qp_in->last_in |= COMPLETE; >@@ -352,7 +349,7 @@ > } > > /* Add an entry to the 'ipq' queue for a newly received IP datagram. */ >-static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph) >+static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user) > { > struct ipq *qp; > >@@ -364,6 +361,7 @@ > qp->id = iph->id; > qp->saddr = iph->saddr; > qp->daddr = iph->daddr; >+ qp->user = user; > qp->len = 0; > qp->meat = 0; > qp->fragments = NULL; >@@ -386,7 +384,7 @@ > /* Find the correct entry in the "incomplete datagrams" queue for > * this IP datagram, and create new one, if nothing is found. > */ >-static inline struct ipq *ip_find(struct iphdr *iph) >+static inline struct ipq *ip_find(struct iphdr *iph, u32 user) > { > __u16 id = iph->id; > __u32 saddr = iph->saddr; >@@ -400,7 +398,8 @@ > if(qp->id == id && > qp->saddr == saddr && > qp->daddr == daddr && >- qp->protocol == protocol) { >+ qp->protocol == protocol && >+ qp->user == user) { > atomic_inc(&qp->refcnt); > read_unlock(&ipfrag_lock); > return qp; >@@ -408,7 +407,7 @@ > } > read_unlock(&ipfrag_lock); > >- return ip_frag_create(hash, iph); >+ return ip_frag_create(hash, iph, user); > } > > /* Add new segment to existing queue. */ >@@ -642,7 +641,7 @@ > } > > /* Process an incoming IP datagram fragment. */ >-struct sk_buff *ip_defrag(struct sk_buff *skb) >+struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user) > { > struct iphdr *iph = skb->nh.iph; > struct ipq *qp; >@@ -657,7 +656,7 @@ > dev = skb->dev; > > /* Lookup (or create) queue header */ >- if ((qp = ip_find(iph)) != NULL) { >+ if ((qp = ip_find(iph, user)) != NULL) { > struct sk_buff *ret = NULL; > > spin_lock(&qp->lock); >@@ -689,10 +688,4 @@ > add_timer(&ipfrag_secret_timer); > } > >-void ipfrag_flush(void) >-{ >- __ip_evictor(0); >-} >- > EXPORT_SYMBOL(ip_defrag); >-EXPORT_SYMBOL(ipfrag_flush); >diff -Naru a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c >--- a/net/ipv4/ip_input.c 2005-03-29 07:19:50 -08:00 >+++ b/net/ipv4/ip_input.c 2005-03-29 07:19:50 -08:00 >@@ -172,7 +172,7 @@ > (!sk->sk_bound_dev_if || > sk->sk_bound_dev_if == skb->dev->ifindex)) { > if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { >- skb = ip_defrag(skb); >+ skb = ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN); > if (skb == NULL) { > read_unlock(&ip_ra_lock); > return 1; >@@ -273,7 +273,7 @@ > */ > > if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { >- skb = ip_defrag(skb); >+ skb = ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER); > if (!skb) > return 0; > } >diff -Naru a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c >--- a/net/ipv4/ipvs/ip_vs_core.c 2005-03-29 07:19:50 -08:00 >+++ b/net/ipv4/ipvs/ip_vs_core.c 2005-03-29 07:19:50 -08:00 >@@ -544,9 +544,9 @@ > } > > static inline struct sk_buff * >-ip_vs_gather_frags(struct sk_buff *skb) >+ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user) > { >- skb = ip_defrag(skb); >+ skb = ip_defrag(skb, user); > if (skb) > ip_send_check(skb->nh.iph); > return skb; >@@ -620,7 +620,7 @@ > > /* reassemble IP fragments */ > if (skb->nh.iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) { >- skb = ip_vs_gather_frags(skb); >+ skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT); > if (!skb) > return NF_STOLEN; > *pskb = skb; >@@ -759,7 +759,7 @@ > /* reassemble IP fragments */ > if (unlikely(iph->frag_off & __constant_htons(IP_MF|IP_OFFSET) && > !pp->dont_defrag)) { >- skb = ip_vs_gather_frags(skb); >+ skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT); > if (!skb) > return NF_STOLEN; > iph = skb->nh.iph; >@@ -839,7 +839,8 @@ > * forward to the right destination host if relevant. > * Currently handles error types - unreachable, quench, ttl exceeded. > */ >-static int ip_vs_in_icmp(struct sk_buff **pskb, int *related) >+static int >+ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum) > { > struct sk_buff *skb = *pskb; > struct iphdr *iph; >@@ -853,7 +854,9 @@ > > /* reassemble IP fragments */ > if (skb->nh.iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) { >- skb = ip_vs_gather_frags(skb); >+ skb = ip_vs_gather_frags(skb, >+ hooknum == NF_IP_LOCAL_IN ? >+ IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD); > if (!skb) > return NF_STOLEN; > *pskb = skb; >@@ -962,7 +965,7 @@ > > iph = skb->nh.iph; > if (unlikely(iph->protocol == IPPROTO_ICMP)) { >- int related, verdict = ip_vs_in_icmp(pskb, &related); >+ int related, verdict = ip_vs_in_icmp(pskb, &related, hooknum); > > if (related) > return verdict; >@@ -1057,7 +1060,7 @@ > if ((*pskb)->nh.iph->protocol != IPPROTO_ICMP) > return NF_ACCEPT; > >- return ip_vs_in_icmp(pskb, &r); >+ return ip_vs_in_icmp(pskb, &r, hooknum); > } > > >diff -Naru a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c >--- a/net/ipv4/netfilter/ip_conntrack_core.c 2005-03-29 07:19:50 -08:00 >+++ b/net/ipv4/netfilter/ip_conntrack_core.c 2005-03-29 07:19:50 -08:00 >@@ -936,29 +936,22 @@ > } > } > >-int ip_ct_no_defrag; >- > /* Returns new sk_buff, or NULL */ > struct sk_buff * >-ip_ct_gather_frags(struct sk_buff *skb) >+ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user) > { > struct sock *sk = skb->sk; > #ifdef CONFIG_NETFILTER_DEBUG > unsigned int olddebug = skb->nf_debug; > #endif > >- if (unlikely(ip_ct_no_defrag)) { >- kfree_skb(skb); >- return NULL; >- } >- > if (sk) { > sock_hold(sk); > skb_orphan(skb); > } > > local_bh_disable(); >- skb = ip_defrag(skb); >+ skb = ip_defrag(skb, user); > local_bh_enable(); > > if (!skb) { >diff -Naru a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c >--- a/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-03-29 07:19:50 -08:00 >+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-03-29 07:19:50 -08:00 >@@ -391,7 +391,10 @@ > > /* Gather fragments. */ > if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { >- *pskb = ip_ct_gather_frags(*pskb); >+ *pskb = ip_ct_gather_frags(*pskb, >+ hooknum == NF_IP_PRE_ROUTING ? >+ IP_DEFRAG_CONNTRACK_IN : >+ IP_DEFRAG_CONNTRACK_OUT); > if (!*pskb) > return NF_STOLEN; > } >@@ -823,12 +826,6 @@ > cleanup_defraglocalops: > nf_unregister_hook(&ip_conntrack_defrag_local_out_ops); > cleanup_defragops: >- /* Frag queues may hold fragments with skb->dst == NULL */ >- ip_ct_no_defrag = 1; >- synchronize_net(); >- local_bh_disable(); >- ipfrag_flush(); >- local_bh_enable(); > nf_unregister_hook(&ip_conntrack_defrag_ops); > cleanup_proc_stat: > #ifdef CONFIG_PROC_FS >diff -Naru a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c >--- a/net/ipv4/netfilter/ip_nat_standalone.c 2005-03-29 07:19:50 -08:00 >+++ b/net/ipv4/netfilter/ip_nat_standalone.c 2005-03-29 07:19:50 -08:00 >@@ -195,7 +195,7 @@ > I'm starting to have nightmares about fragments. */ > > if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { >- *pskb = ip_ct_gather_frags(*pskb); >+ *pskb = ip_ct_gather_frags(*pskb, IP_DEFRAG_NAT_OUT); > > if (!*pskb) > return NF_STOLEN; >diff -Naru a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c >--- a/net/ipv4/ip_output.c 2005-03-16 12:07:44 -08:00 >+++ b/net/ipv4/ip_output.c 2005-03-16 12:07:44 -08:00 >@@ -504,6 +504,7 @@ > /* Prepare header of the next frame, > * before previous one went down. */ > if (frag) { >+ frag->ip_summed = CHECKSUM_NONE; > frag->h.raw = frag->data; > frag->nh.raw = __skb_push(frag, hlen); > memcpy(frag->nh.raw, iph, hlen); >diff -Naru a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c >--- a/net/ipv6/ip6_output.c 2005-03-16 12:07:44 -08:00 >+++ b/net/ipv6/ip6_output.c 2005-03-16 12:07:44 -08:00 >@@ -592,6 +592,7 @@ > /* Prepare header of the next frame, > * before previous one went down. */ > if (frag) { >+ frag->ip_summed = CHECKSUM_NONE; > frag->h.raw = frag->data; > fh = (struct frag_hdr*)__skb_push(frag, sizeof(struct frag_hdr)); > frag->nh.raw = __skb_push(frag, hlen);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 81195
:
54763
| 54764