Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 19 Aug 2000 15:56:22 +1000 (Australia/NSW)
From:      Darren Reed <avalon@coombs.anu.edu.au>
To:        luigi@info.iet.unipi.it (Luigi Rizzo)
Cc:        freebsd-security@freefall.freebsd.org
Subject:   Re: [avalon@COOMBS.ANU.EDU.AU: Ip packet filtering with bridging on
Message-ID:  <200008190556.PAA16336@cairo.anu.edu.au>
In-Reply-To: <200008182048.WAA09758@info.iet.unipi.it> from "Luigi Rizzo" at Aug 18, 2000 10:48:05 PM

next in thread | previous in thread | raw e-mail | index | archive | help
In some mail from Luigi Rizzo, sie said:
> 
> I was informed by a few people of a thread on alleged problems with
> ipfw+bridging, so i think i should say a few things on the subject.
> 
> Darren was complaining that net/bridge.c was missing some sanity
> checks on packets before passing them to ip_fw_chk().  I looked at
> his proposed fix on -security archives (i am not subscribed to the
> list, this is why i did not react).
> 
> I am not sure which version of FreeBSD Darren refers to -- the

What's in -current.

> missing checks were there when i committed the code to 3.x and 4.x
> -- only thing, they are|were located in /sys/netinet/ip_fw.c,
> function ip_fw_chk() near this section of code:
[...]

Huh ?  Can you point to *exact* versions of the relevant files ?

I'm looking at /sys/net/bridge.c (1.23) and I see:

        if (ntohs(eh->ether_type) != ETHERTYPE_IP)
            goto forward ; /* not an IP packet, ipfw is not appropriate */
        /*
         * In this section, canfree=1 means m is the same as *m0.
         * canfree==0 means m is a copy. We need to make a copy here
         * (to be destroyed on exit from the firewall section) because
         * the firewall itself might destroy the packet.
         * (This is not very smart... i should really change ipfw to
         * leave the pkt alive!)
         */
        if (canfree == 0 ) {
            /*
             * Need to make a copy (and for good measure, make sure that
             * the header is contiguous). The original is still in *m0
             */
            int needed = min(MHLEN, max_protohdr) ;
            needed = min(needed, (*m0)->m_len ) ;

            m = m_copypacket( (*m0), M_DONTWAIT);
            if (m == NULL) {
                printf("-- bdg: m_copypacket failed.\n") ;
                return ENOBUFS ;
            }
            if (m->m_len < needed && (m = m_pullup(m, needed)) == NULL) {
                printf("-- bdg: pullup failed.\n") ;
                return ENOBUFS ;
            }
        }

Which is *NOT* sufficient.

Version 1.138 of ip_fw.c does not have "ETHERTYPE_IP" anywhere in it.

Version 1.131.2.1 (FreeBSD 4.0) has this in ip_fw.c:

            case ETHERTYPE_IP :
                if ((*m)->m_len<sizeof(struct ether_header) + sizeof(struct ip))
                    goto non_ip ;
                ip = (struct ip *)(eh + 1 );
                if (ip->ip_v != IPVERSION)
                    goto non_ip ;
                hlen = ip->ip_hl << 2;
                if (hlen < sizeof(struct ip)) /* minimum header length */
                    goto non_ip ;
                if ((*m)->m_len < 14 + hlen + 14) {
                    printf("-- m_len %d, need more...\n", (*m)->m_len);
                    goto non_ip ;
                }
                offset = (ip->ip_off & IP_OFFMASK);
                break ;
            default :
non_ip:         ip = NULL ;
                break ;
            }

Which almost does the right thing.  It will cause some packets to be
dropped when they shouldn't (what is "14 + hlen + 14" ?).  Having looked
at other ipfw code, it would *appear* this is a cheap way of saying
"sizeof(struct ether_header) + hlen + some_magic_bytes", where
some_magic_bytes is hopefully enough to get all the important TCP fields.
Furthermore, ip_len is never checked ... it's unclear if this poses a
threat to icmp_error()/tcp_respond().  Luckily the "state" code for ipfw
has not reached a level of sophistication where it examines the ICMP
payload as does IP Filter.

Darren


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-security" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200008190556.PAA16336>