Bug report: dhcp+LDAP with dynamic configuration leaks memory; DoS potential

Alex Bligh alex at alex.org.uk
Wed May 4 16:38:47 UTC 2011


Extensive investigation shows dhcp+ldap is leaking memory. Sending 494
discover packets for which there is an LDAP record leaks around 90k
of memory, so this is reasonably serious.

This bug is present on dhcp3-server-ldap 3.1.3-2ubuntu3.2 and
dhcp 4.2.1-P1 release built from source. It appears to be a
reasonably fundamental problem with how the ldap patch works.

The leak appears to happen in find_haddr_in_ldap. At line 1836, the
following happens:

>       if (!clone_group (&host->group, root_group, MDL))
>         {
>           log_fatal ("can't clone group for host %s", host->name);
>           host_dereference (&host, MDL);
>           ldap_msgfree (res);
>           return (0);
>         }
>
>       ldap_parse_options (ent, host->group, HOST_DECL, host, NULL);
>
>       *hp = host;
>       ldap_msgfree (res);
>       return (1);
>     }

The clone_group allocates memory, and that memory is never freed
as far as I can tell. valgrind agrees:

> ==30077== 27,832 bytes in 497 blocks are definitely lost in loss record
> 214 of 231 ==30077==    at 0x4C274A8: malloc (vg_replace_malloc.c:236)
> ==30077==    by 0x4940D5: dmalloc (alloc.c:75)
> ==30077==    by 0x456EDC: group_allocate (alloc.c:176)
> ==30077==    by 0x46B198: clone_group (memory.c:145)
> ==30077==    by 0x4564FF: find_haddr_in_ldap (ldap.c:1836)
> ==30077==    by 0x4372D8: find_hosts_by_haddr (mdb.c:606)
> ==30077==    by 0x410354: find_lease (dhcp.c:3318)
> ==30077==    by 0x4071CB: dhcpdiscover (dhcp.c:278)
> ==30077==    by 0x40707A: dhcp (dhcp.c:225)
> ==30077==    by 0x473D38: do_packet (options.c:3759)
> ==30077==    by 0x46142B: got_one (discover.c:1401)
> ==30077==    by 0x49923E: omapi_iscsock_cb (dispatch.c:174)
> ==30077==
> ==30077== 61,256 (31,616 direct, 29,640 indirect) bytes in 494 blocks are
> definitely lost in loss record 219 of 231 ==30077==    at 0x4C274A8:
> malloc (vg_replace_malloc.c:236)
> ==30077==    by 0x4940D5: dmalloc (alloc.c:75)
> ==30077==    by 0x457875: option_cache_allocate (alloc.c:650)
> ==30077==    by 0x40E575: ack_lease (dhcp.c:2643)
> ==30077==    by 0x407720: dhcpdiscover (dhcp.c:397)
> ==30077==    by 0x40707A: dhcp (dhcp.c:225)
> ==30077==    by 0x473D38: do_packet (options.c:3759)
> ==30077==    by 0x46142B: got_one (discover.c:1401)
> ==30077==    by 0x49923E: omapi_iscsock_cb (dispatch.c:174)
> ==30077==    by 0x570C4E: internal_fdwatch_read (socket.c:3406)
> ==30077==    by 0x577754: isc__taskmgr_dispatch (task.c:1012)
> ==30077==    by 0x566E3A: evloop (app.c:497)
> ==30077==

In this test, approximately 494 DHCP discover packets were generated
and sent.

As far as I can understand how the memory handling works here (which
is perhaps not sufficient), the host/group entry is not being added
to dhcpd's cache, so every dhcp discover results in a new LDAP
query (which is fair enough). However, the group entry is never being
freed (perhaps because the caller expects the host entry to be one
that is already in the main hash).

This presents a denial of service attack opportunity. A simple perl
script can send tens or even hundreds of packets a second.

Any ideas on how this can be fixed? Reason for interest: it is affecting
my SQL/DBI patch, which was heavily based on the LDAP patch.

I can provide perl code which will duplicate this if necessary.

-- 
Alex Bligh




More information about the dhcp-users mailing list