All, I found this bug running Ubuntu 11.10, I managed to hang the operating system with the CPU pegged at 100% after sending it a malformed IP option packet. I had installed the xtables-addons-dmks package installed via apt-get. The Ubuntu 11.10 distribution runs with the "3.0.0-12 #20-Ubuntu SMP" kernel. AFAIK, there should be little modifications to the code compared what is installed in git repository available on the web. To reproduce this issue: 1. Install Ubuntu 11.10 2. apt-get install xtables-addon-dmks 3. iptables -I INPUT 1 -m ipv4options --any -j LOG --log-prefix "PACKET WITH IP-OPTIONS DETECTED" On a different computer (attacker), 4. Download, and install the isic (ip stack integrity checker) from http://isic.sourceforge.net 5. Run a test of the ip-stack to the victim (Ubuntu 11.10) computer (attacker: 192.168.111.100, victim: 192.168.111.200). sudo tcpsic -s 192.168.111.100,69 -d 192.168.111.200 -x 2 -m 1000 -T 30 -t 50 6. Victim PC freezes, no mouse, no movement; just dead. Further investigation showed that the xt_ipv4options.ko module was the culprit. The problem appeared to be that the ipv4option_rd() function entered a infinite loop when an ip-option of length 0 was encountered. I grepped the Linux kernel for similar code and modified the code in xt_ipv4options.c to correct this behavior. In addition, it seems like the --any option wasn't working correctly to begin with. Any chances for this patch being accepted? Regards, - Eivind --- /tmp/tmp.13465.100 2011-11-03 09:20:11.000000000 -0700 +++ xtables-addons/extensions/xt_ipv4options.c 2011-11-02 13:03:14.000000000 -0700 @@ -15,14 +15,32 @@ #include "xt_ipv4options.h" #include "compat_xtables.h" -static uint32_t ipv4options_rd(const uint8_t *data, int len) +static uint32_t ipv4options_rd(const uint8_t *ptr, int len) { uint32_t opts = 0; + uint32_t olen = 0; while (len >= 2) { - opts |= 1 << (data[0] & 0x1F); - len -= data[1]; - data += data[1]; + + /* Handle special options */ + switch (*ptr) { + case IPOPT_END: + return opts; + case IPOPT_NOOP: + len--; + ptr++; + continue; + } + + /* Get the length of the option */ + olen = ptr[1]; + if (olen < 2 || olen > len) + return opts; + + /* Set the option bit, and incr/decr the invariants */ + opts |= 1 << (*ptr & 0x1F); + len -= olen; + ptr += olen; } return opts; @@ -36,13 +54,20 @@ uint32_t opts = 0; uint16_t len = ip_hdrlen(skb) - sizeof(struct iphdr); - if (len > 0) + if (len > 0) { opts = ipv4options_rd((const void *)iph + sizeof(struct iphdr), len); + if(info->flags & XT_V4OPTS_ANY) { + return !!opts; /* !! to make bool value */ + }else { opts ^= info->invert; opts &= info->map; - return (info->flags & XT_V4OPTS_ANY) ? opts : opts == info->map; + return (opts == info->map); + } + } + + return 0; } -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html