ipfw tcpopt_match and m_pullup()

Karim Fodil-Lemelin kfl at xiplink.com
Wed Mar 23 18:51:40 UTC 2011


Hi,

This is something that came up at work. While the ipfw code make sure 
the tcp header is contiguous in ipfw_chck by calling PULLUP_TO, the code 
does not guarantee 'contiguousity' of the TCP option space.

This means that code that walks the option space in ipfw (namely 
tcpopts_match) could be falling off the edge of the mbuf container and 
lead to all sorts of problems. Following is a patch that fixed the 
problem for us and hopefully this gets pushed in this form or another to 
the freebsd tree for others to benefit.

Best regards,

Karim.

#svn diff
Index: ip_fw2.c
===================================================================
--- ip_fw2.c    (revision 218930)
+++ ip_fw2.c    (working copy)
@@ -949,6 +949,11 @@

                         case IPPROTO_TCP:
                                 PULLUP_TO(hlen, ulp, struct tcphdr);
+                               /* kfl: check 'contiguousity' of the 
option space */
+                               if (m->m_len < (hlen + (TCP(ulp)->th_off 
<< 2))) {
+                                 if ((m = m_pullup(m, 
hlen+(TCP(ulp)->th_off << 2))) == NULL)
+                                   goto pullup_failed;
+                               }
                                 dst_port = TCP(ulp)->th_dport;
                                 src_port = TCP(ulp)->th_sport;
                                 /* save flags for dynamic rules */
@@ -1117,6 +1122,11 @@
                         switch (proto) {
                         case IPPROTO_TCP:
                                 PULLUP_TO(hlen, ulp, struct tcphdr);
+                               /* kfl: check 'contiguousity' of the 
option space */
+                               if (m->m_len < (hlen + (TCP(ulp)->th_off 
<< 2))) {
+                                 if ((m = m_pullup(m, 
hlen+(TCP(ulp)->th_off << 2))) == NULL)
+                                   goto pullup_failed;
+                               }
                                 dst_port = TCP(ulp)->th_dport;
                                 src_port = TCP(ulp)->th_sport;
                                 /* save flags for dynamic rules */



More information about the freebsd-ipfw mailing list