In ip_lengthcheck(), make sure that pkthdr.len is not less than "IP total
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Tue, 28 Oct 2008 07:09:26 +0000 (07:09 +0000)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Tue, 28 Oct 2008 07:09:26 +0000 (07:09 +0000)
length" in IP header.  Change the related testing in ip_input() and
ipflow_fastforward() into assertion.

sys/netinet/ip_demux.c
sys/netinet/ip_flow.c
sys/netinet/ip_input.c

index 9323ec5..cebb1f4 100644 (file)
@@ -30,7 +30,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/netinet/ip_demux.c,v 1.43 2008/10/28 04:35:12 sephe Exp $
+ * $DragonFly: src/sys/netinet/ip_demux.c,v 1.44 2008/10/28 07:09:26 sephe Exp $
  */
 
 #include "opt_inet.h"
@@ -89,6 +89,8 @@ INP_MPORT_HASH(in_addr_t faddr, in_addr_t laddr,
  * o  IP header (including any possible IP options) is in one mbuf (m_len).
  * o  IP header length is not less than the minimum (sizeof(struct ip)).
  * o  IP total length is not less than IP header length.
+ * o  IP datagram resides completely in the mbuf chain,
+ *    i.e. pkthdr.len >= IP total length.
  *
  * If the packet is a UDP datagram,
  * o  IP header (including any possible IP options) and UDP header are in
@@ -146,6 +148,15 @@ ip_lengthcheck(struct mbuf **mp)
 
        iplen = ntohs(ip->ip_len);
 
+       /*
+        * Check that the amount of data in the buffers is as
+        * at least much as the IP header would have us expect.
+        */
+       if (m->m_pkthdr.len < iplen) {
+               ipstat.ips_tooshort++;
+               goto fail;
+       }
+
        /*
         * Fragments other than the first fragment don't have much
         * length information.
index 69f1c06..3872761 100644 (file)
@@ -34,7 +34,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/netinet/ip_flow.c,v 1.9.2.2 2001/11/04 17:35:31 luigi Exp $
- * $DragonFly: src/sys/netinet/ip_flow.c,v 1.26 2008/10/27 09:57:11 sephe Exp $
+ * $DragonFly: src/sys/netinet/ip_flow.c,v 1.27 2008/10/28 07:09:26 sephe Exp $
  */
 
 #include <sys/param.h>
@@ -193,18 +193,19 @@ ipflow_fastforward(struct mbuf *m)
 
        /* length checks already done in ip_mport() */
        KASSERT(m->m_len >= sizeof(struct ip), ("IP header not in one mbuf"));
+       ip = mtod(m, struct ip *);
 
        /*
-        * IP header with no option and valid version and length
+        * IP header with no option and valid version
         */
-       ip = mtod(m, struct ip *);
-       iplen = ntohs(ip->ip_len);
-       if (ip->ip_v != IPVERSION || ip->ip_hl != (sizeof(struct ip) >> 2) ||
-           iplen > m->m_pkthdr.len)
+       if (ip->ip_v != IPVERSION || ip->ip_hl != (sizeof(struct ip) >> 2))
                return 0;
 
+       iplen = ntohs(ip->ip_len);
        /* length checks already done in ip_mport() */
-       KKASSERT(iplen >= sizeof(struct ip));
+       KASSERT(iplen >= sizeof(struct ip),
+               ("total length less then header length"));
+       KASSERT(m->m_pkthdr.len >= iplen, ("mbuf too short"));
 
        /*
         * Find a flow.
index 883accb..2a15264 100644 (file)
@@ -65,7 +65,7 @@
  *
  *     @(#)ip_input.c  8.2 (Berkeley) 1/4/94
  * $FreeBSD: src/sys/netinet/ip_input.c,v 1.130.2.52 2003/03/07 07:01:28 silby Exp $
- * $DragonFly: src/sys/netinet/ip_input.c,v 1.114 2008/10/28 03:07:28 sephe Exp $
+ * $DragonFly: src/sys/netinet/ip_input.c,v 1.115 2008/10/28 07:09:26 sephe Exp $
  */
 
 #define        _IP_VHL
@@ -493,7 +493,7 @@ ip_input(struct mbuf *m)
        hlen = IP_VHL_HL(ip->ip_vhl) << 2;
        /* length checks already done in ip_mport() */
        KASSERT(hlen >= sizeof(struct ip), ("IP header len too small"));
-       KASSERT(m->m_len >= hlen, ("packet shorter than IP header length"));
+       KASSERT(m->m_len >= hlen, ("complete IP header not in one mbuf"));
 
        /* 127/8 must not appear on wire - RFC1122 */
        if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
@@ -527,22 +527,15 @@ ip_input(struct mbuf *m)
         * Convert fields to host representation.
         */
        ip->ip_len = ntohs(ip->ip_len);
-       if (ip->ip_len < hlen) {
-               ipstat.ips_badlen++;
-               goto bad;
-       }
        ip->ip_off = ntohs(ip->ip_off);
 
+       /* length checks already done in ip_mport() */
+       KASSERT(ip->ip_len >= hlen, ("total length less then header length"));
+       KASSERT(m->m_pkthdr.len >= ip->ip_len, ("mbuf too short"));
+
        /*
-        * Check that the amount of data in the buffers
-        * is as at least much as the IP header would have us expect.
-        * Trim mbufs if longer than we expect.
-        * Drop packet if shorter than we expect.
+        * Trim mbufs if longer than the IP header would have us expect.
         */
-       if (m->m_pkthdr.len < ip->ip_len) {
-               ipstat.ips_tooshort++;
-               goto bad;
-       }
        if (m->m_pkthdr.len > ip->ip_len) {
                if (m->m_len == m->m_pkthdr.len) {
                        m->m_len = ip->ip_len;