Either the IP masq code or my brain is broken.

David Woodhouse (David.Woodhouse@mvhi.com)
Mon, 26 Oct 1998 21:48:32 +0000


To help me trace the recurring IP masquerade oopsen that people are seeing, I
made this simple patch to add a call to verify_area() for the packet being
demasqueraded, and whinge if it fails.

Could anyone tell me why it keeps failing? (Where failing == printing my
'whinge' message.) The complaint is happening quite frequently, but the
machine wasn't going down that often before, so it must be catching cases that
didn't cause an oops (whinge once a minute vs. crash once a fortnight.)

My original check was: if (h.raw + size > skb->tail)
That didn't ever fail, but it didn't catch and stop the oops, either.
Now what?

(Alan - now I've had independent confirmation of this problem without ISDN
present, could you add it to http://roadrunner/jobs.shtml please? I'll send
more details if you've missed them. Basically it oopses on the memory access in
the first partial_csum after my sanity check)

--- ip_masq.c.nocheck Fri Oct 23 11:49:11 1998
+++ ip_masq.c Mon Oct 26 18:10:41 1998
@@ -1703,6 +1703,25 @@
* this function.
*/

+
+static void formatoutput_byte_hexdump(unsigned char *data, int num)
+{
+ int c;
+
+ if (num > 64) num = 64;
+
+ for (c=0; c< num;)
+ {
+ printk("%5.5X: %2.2X",c,data[c]);
+
+ for (c++ ; c%16 && c<num; c++)
+ {
+ printk(" %2.2X",data[c]);
+ }
+ printk("\n");
+ }
+}
+
int ip_fw_demasquerade(struct sk_buff **skb_p)
{
struct sk_buff *skb = *skb_p;
@@ -1758,6 +1777,26 @@
{
case CHECKSUM_NONE:
doff = proto_doff(iph->protocol, h.raw);
+ if (verify_area(VERIFY_READ, (char *)h.raw, size) || doff > size)
+ {
+ /* Packet of length iph->tot_len doesn't fit in the skb!
+ * Whinge like buggery. DW.
+ */
+
+ printk(KERN_CRIT "Bad packet in ip_fw_demasquerade()\n");
+ printk(KERN_CRIT "Standard 2.1.125 kernel would have oopsed and died now\n");
+ if (doff > size)
+ printk(KERN_CRIT "doff (%x) > size (%x)!\n", doff, size);
+ printk(KERN_CRIT "Reported size in IP header: %x (+ offset %x = %x)\n",size, doff, size + doff);
+ printk(KERN_CRIT "Size of actual data in sk_buff: %x\n", skb->len);
+ printk(KERN_CRIT "h.raw + size = %p, skb->tail = %p\n",h.raw + size, skb->tail);
+ if (skb->dev && skb->dev->name)
+ printk(KERN_CRIT "Packet arrived on interface %s\n", skb->dev->name);
+ printk(KERN_CRIT "Packet dump follows...\n");
+ formatoutput_byte_hexdump(skb->h.raw, skb->len);
+
+ return -1;
+ }
csum = csum_partial(h.raw + doff, size - doff, 0);
skb->csum = csum_partial(h.raw , doff, csum);

---- ---- ----
David Woodhouse David.Woodhouse@mvhi.com Office: (+44) 1223 810302
Project Leader, Process Information Systems Mobile: (+44) 976 658355
Axiom (Cambridge) Ltd., Swaffham Bulbeck, Cambridge, CB5 0NA, UK.
finger dwmw2@ferret.lmh.ox.ac.uk for PGP key.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/