Panic in ebtables-5 with 2.4.25 with ip_conntrack and vlan
Adam Osuchowski <adwol-QJnc/[email protected]>
| Newsgroups | gmane.linux.network.bridge.ebtables.devel |
|---|---|
| Organization | Computer Centre of The Silesian University of Technology |
| Message-ID | <[email protected]> |
Hello,
there is small problem with ebtables 5 on 2.4.24 & 2.4.25 kernels. When
fragmented IP packet embedded in tagged vlan frame traverses the kernel with
ip_conntrack enabled a panic occures due to memory underflow. The
skb_reserve() function used in ip_fragment() function:
skb_reserve(skb2, (dev->hard_header_len+15)&~15);
doesn't reserve enough space to handle this frame correctly. The initial
reserved 14 octets for ethernet header between skb->head and skb->data are not
enough to carry tagged ethernet header which length is 18 octets. Since we
have actually reserved 16 octets (aligning) the missed difference is only 2
octets long. Later, nf_bridge_maybe_copy_header() function assumes that there
is 18 octets free space and copies original vlan ethernet header from private
field and skb->data pointer is moving back by 4 octets:
memcpy(skb->data - 18, skb->nf_bridge->data, 18);
skb_push(skb, 4);
Next, in br_dev_queue_push_xmit() function tries to move back this pointer by
another 14 octets (ETH_HLEN). In result skb_push() panics.
The following patch resolve this problem but maybe there is better way to fix
it.
Regards,
Adam Osuchowski
Tomasz Dubinski
--- linux-2.4.25/net/ipv4/ip_output.c.orig 2003-11-28 19:26:21.000000000 +0100
+++ linux-2.4.25/net/ipv4/ip_output.c 2004-02-20 12:12:56.000000000 +0100
@@ -792,10 +792,12 @@
*/
while(left > 0) {
+ int vlan_pad = (skb->nf_bridge && (*(unsigned short *)&(skb->nf_bridge->data[3]) == __constant_htons(ETH_P_8021Q))) ? 4 : 0;
+
len = left;
/* IF: it doesn't fit, use 'mtu' - the data space left */
- if (len > mtu)
- len = mtu;
+ if (len > mtu - vlan_pad)
+ len = mtu - vlan_pad;
/* IF: we are not sending upto and including the packet end
then align the next start on an eight byte boundary */
if (len < left) {
@@ -805,7 +807,7 @@
* Allocate buffer.
*/
- if ((skb2 = alloc_skb(len+hlen+dev->hard_header_len+15,GFP_ATOMIC)) == NULL) {
+ if ((skb2 = alloc_skb(len+hlen+dev->hard_header_len+15 + vlan_pad, GFP_ATOMIC)) == NULL) {
NETDEBUG(printk(KERN_INFO "IP: frag: no memory for new fragment!\n"));
err = -ENOMEM;
goto fail;
@@ -817,7 +819,7 @@
skb2->pkt_type = skb->pkt_type;
skb2->priority = skb->priority;
- skb_reserve(skb2, (dev->hard_header_len+15)&~15);
+ skb_reserve(skb2, (dev->hard_header_len+15+vlan_pad)&~15);
skb_put(skb2, len + hlen);
skb2->nh.raw = skb2->data;
skb2->h.raw = skb2->data + hlen;
--
## Adam Osuchowski adwol-QJnc/[email protected], [email protected]
## Silesian University of Technology, Computer Centre Gliwice, Poland
-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now.
Build and deploy apps & Web services for Linux with
a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click