https://bugs.openldap.org/show_bug.cgi?id=10577
Issue ID: 10577 Summary: Memory leak in client-side libldap response handling when a malformed BER message causes an error. Product: OpenLDAP Version: 2.6.8 Hardware: x86_64 OS: Linux Status: UNCONFIRMED Keywords: needs_review Severity: normal Priority: --- Component: client tools Assignee: bugs@openldap.org Reporter: thetrenshow157@gmail.com Target Milestone: ---
Created attachment 1195 --> https://bugs.openldap.org/attachment.cgi?id=1195&action=edit Reproduction script
During client-side libldap fuzzing, a memory leak was found when processing a malformed BER response.
If a response contains a valid message ID matching an outstanding request, `ldap_find_request_by_msgid()` increments the `LDAPRequest` reference count. If the following TLV declares a length larger than the remaining BER data, `ber_peek_tag()` returns `LBER_ERROR` and `try_read1msg()` returns `-1` without releasing the acquired request reference.
As a result, the `LDAPRequest` and its associated allocations are leaked.
The attached reproducer triggers the issue with a malformed BindResponse, but the issue is not specific to the request type.
The Valgrind log was collected with OpenLDAP 2.6.8, but the memory leak is still reproducible on the latest development branch. Although such a malformed response is not expected from a compliant server, it would still be better to handle this error path without leaking memory. I have attached the reproducer script and the Valgrind log to this message.
Valgrind log:
==307307== Memcheck, a memory error detector ==307307== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al. ==307307== Using Valgrind-3.26.0 and LibVEX; rerun with -h for copyright info ==307307== Command: ldapsearch -x -H ldap://127.0.0.1:37095/ -D cn=Directory\ Manager -w password -b dc=example,dc=com -s base (objectClass=*) -o nettimeout=2 -l 2 ==307307== ldap_result: Can't contact LDAP server (-1) ==307307== ==307307== HEAP SUMMARY: ==307307== in use at exit: 4,290 bytes in 4 blocks ==307307== total heap usage: 165 allocs, 161 frees, 106,847 bytes allocated ==307307== ==307307== 4,276 (136 direct, 4,140 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 4 ==307307== at 0x48664A4: calloc (vg_replace_malloc.c:1678) ==307307== by 0x48E7A4C: ber_memcalloc_x (memory.c:283) ==307307== by 0x48AA75A: ldap_send_server_request (request.c:349) ==307307== by 0x48AAD8F: ldap_send_initial_request (request.c:169) ==307307== by 0x489B296: ldap_sasl_bind (sasl.c:164) ==307307== by 0x400F226: tool_bind (common.c:1593) ==307307== by 0x400593A: main (ldapsearch.c:1109) ==307307== ==307307== LEAK SUMMARY: ==307307== definitely lost: 136 bytes in 1 blocks ==307307== indirectly lost: 4,140 bytes in 2 blocks ==307307== possibly lost: 0 bytes in 0 blocks ==307307== still reachable: 14 bytes in 1 blocks ==307307== suppressed: 0 bytes in 0 blocks ==307307== Reachable blocks (those to which a pointer was found) are not shown. ==307307== To see them, rerun with: --leak-check=full --show-leak-kinds=all ==307307== ==307307== For lists of detected and suppressed errors, rerun with: -s ==307307== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)