diff options
author | bms <bms@FreeBSD.org> | 2003-09-23 16:39:31 +0000 |
---|---|---|
committer | bms <bms@FreeBSD.org> | 2003-09-23 16:39:31 +0000 |
commit | 3d68723716bfa0987b31777ec7ab2c4cb4bd7030 (patch) | |
tree | 39b365ca4e6e45f1b4ba32e515175fab4b7f374e | |
parent | 9957f857c4e5ca3260e0cffadbf68c55f72fa332 (diff) | |
download | FreeBSD-src-3d68723716bfa0987b31777ec7ab2c4cb4bd7030.zip FreeBSD-src-3d68723716bfa0987b31777ec7ab2c4cb4bd7030.tar.gz |
Fix a bug in arplookup(), whereby a hostile party on a locally
attached network could exhaust kernel memory, and cause a system
panic, by sending a flood of spoofed ARP requests.
Approved by: jake (mentor)
Reported by: Apple Product Security <product-security@apple.com>
-rw-r--r-- | UPDATING | 6 | ||||
-rw-r--r-- | sys/netinet/if_ether.c | 20 |
2 files changed, 20 insertions, 6 deletions
@@ -17,6 +17,12 @@ NOTE TO PEOPLE WHO THINK THAT 5.0-CURRENT IS SLOW: developers choose to disable these features on build machines to maximize performance. +20030923: + Fix a bug in arplookup(), whereby a hostile party on a locally + attached network could exhaust kernel memory, and cause a system + panic, by sending a flood of spoofed ARP requests. See + FreeBSD-SA-03:14.arp. + 20030915: A change to /etc/defaults/rc.conf now causes inetd to be started with `-C 60' if it is not overridden in /etc/rc.conf. This diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index c02ba55..22ca55e 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -918,12 +918,20 @@ arplookup(addr, create, proxy) else if (rt->rt_gateway->sa_family != AF_LINK) why = "gateway route is not ours"; - if (why && create) { - log(LOG_DEBUG, "arplookup %s failed: %s\n", - inet_ntoa(sin.sin_addr), why); - return 0; - } else if (why) { - return 0; + if (why) { + if (create) + log(LOG_DEBUG, "arplookup %s failed: %s\n", + inet_ntoa(sin.sin_addr), why); + + /* If there are no references to this route, purge it */ + if (rt->rt_refcnt <= 0 && + (rt->rt_flags & RTF_WASCLONED) != RTF_WASCLONED) { + rtrequest(RTM_DELETE, + (struct sockaddr *)rt_key(rt), + rt->rt_gateway, rt_mask(rt), + rt->rt_flags, 0); + } + return (0); } return ((struct llinfo_arp *)rt->rt_llinfo); } |