Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 10 Jan 2011 17:31:04 -0500
From:      George Neville-Neil <gnn@neville-neil.com>
To:        Rozhuk.IM@gmail.com
Cc:        freebsd-net@freebsd.org
Subject:   Re: [arp] possible DoS, fixes and improvements
Message-ID:  <5B47152C-9076-4E54-BCD8-A66FF3E00A42@neville-neil.com>
In-Reply-To: <4cfe88b6.1cedd80a.33f5.119d@mx.google.com>
References:  <4cfe88b6.1cedd80a.33f5.119d@mx.google.com>

next in thread | previous in thread | raw e-mail | index | archive | help

On Dec 7, 2010, at 14:19 , rozhuk.im@gmail.com wrote:

> Hi!
>=20
>=20

Hi,

Sorry it has taken me a while to test this.  In the first two cases I =
cannot reproduce your results
on HEAD.  I have attempted to test this with a modified arpwhohas.py =
script using PCS (ports/net/pcs).
I can send very large requests and I see them arrive with tcpdump but =
the kernel just throws them away.

I do not disagree that the code might be wrong, in particular in case 1, =
but I cannot reproduce your results.
If you wish to share your test code with me that would be fine, or you =
can try your test against HEAD
and let me know your result.

> 1. ah->ar_hln - is depend from ar_hrd?
> Yes, and for ARPHRD_ETHER is 6 (ETHER_ADDR_LEN)
> For ARPHRD_IEEE1394 - sizeof(struct fw_hwaddr)
> ah->ar_hln ignored in ether_output: bcopy(ar_tha(ah), edst, =
ETHER_ADDR_LEN);
>=20
> check in in_arpinput:
> 		if (ifp->if_addrlen !=3D ah->ar_hln) {
> 			LLE_WUNLOCK(la);
> 			log(LOG_WARNING,
> 			    "arp from %*D: addr len: new %d, i/f %d
> (ignored)",
> 			    ifp->if_addrlen, (u_char *) ar_sha(ah), ":",
> 			    ah->ar_hln, ifp->if_addrlen);
> 			goto reply;
> 		}
> NO DROP!!!!
> In reply we get:
> 		(void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
> 		(void)memcpy(ar_sha(ah), enaddr, ah->ar_hln);
> Or=20
> 			(void)memcpy(ar_tha(ah), ar_sha(ah), =
ah->ar_hln);
> 			(void)memcpy(ar_sha(ah), &lle->ll_addr, =
ah->ar_hln);
>=20
> How to use it see below.
>=20
>=20
> 2. ah->ar_pln - does not checked!
> We can make big arp request (512 nulls after struct arphdr + 2*6 + =
2*4) ,
> valid for host, set ar_plt =3D 255
> And in reply will receive part of stack or core panic:
> in_arpinput:
> (void)memcpy(ar_spa(ah), &itaddr, ah->ar_pln);
> ...
> m->m_len =3D sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln);
> ( eq arphdr_len(ah) )
>=20
>=20
>=20
> 3. ar_sha(ah) - does not checked for multicast!
> Answers to request my be send to multicast addrs
> Only broadcast and host addr are checked.
> No check is ar_sha(ah) equal to Ethernet.ether_shost
> As result:
> arp -an
> ? (172.16.0.2) at 01:80:c2:00:00:01 on em0 expires in 118 seconds =
[ethernet]
>=20
>=20
>=20
> 4. holded packet my be sended without any locks
>=20
> Current:
> 		if (la->la_hold !=3D NULL) {
> 			struct mbuf *m_hold, *m_hold_next;
>=20
> 			bcopy(L3_ADDR(la), &sa, sizeof(sa));
> 			LLE_WUNLOCK(la);
> 			for (m_hold =3D la->la_hold, la->la_hold =3D =
NULL;
> 			     m_hold !=3D NULL; m_hold =3D m_hold_next) {
> 				m_hold_next =3D m_hold->m_nextpkt;
> 				m_hold->m_nextpkt =3D NULL;
> 				(*ifp->if_output)(ifp, m_hold, &sa, =
NULL);
> 			}
> 		} else
> 			LLE_WUNLOCK(la);
> 		la->la_hold =3D NULL;
> 		la->la_numheld =3D 0;
>=20
> Here we unlock la and then modify them - this is bad idea!
> Patched - see in attached patch.
>=20

This is now fixed in HEAD.  Thanks!

Best,
George




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?5B47152C-9076-4E54-BCD8-A66FF3E00A42>