mirror of
https://github.com/scylladb/scylladb.git
synced 2026-04-25 19:10:42 +00:00
Merge 'ldap: fix double-free of LDAPMessage in poll_results()' from Andrzej Jackowski
In the unregistered-ID branch, ldap_msgfree() was called on a result
already owned by an RAII ldap_msg_ptr, causing a double-free on scope
exit. Remove the redundant manual free.
Fixes: SCYLLADB-1344
Backport: 2026.1, 2025.4, 2025.1 - it's a memory corruption, with a one-line fix, so better backport it everywhere.
Closes scylladb/scylladb#29302
* github.com:scylladb/scylladb:
test: ldap: add regression test for double-free on unregistered message ID
ldap: fix double-free of LDAPMessage in poll_results()
(cherry picked from commit 895fdb6d29)
Closes scylladb/scylladb#29393
Closes scylladb/scylladb#29454
This commit is contained in:
committed by
Botond Dénes
parent
52a3ed4312
commit
5468cd49da
@@ -437,7 +437,6 @@ void ldap_connection::poll_results() {
|
||||
const auto found = _msgid_to_promise.find(id);
|
||||
if (found == _msgid_to_promise.end()) {
|
||||
mylog.error("poll_results: got valid result for unregistered id {}, dropping it", id);
|
||||
ldap_msgfree(result);
|
||||
} else {
|
||||
found->second.set_value(std::move(result_ptr));
|
||||
_msgid_to_promise.erase(found);
|
||||
|
||||
@@ -235,7 +235,7 @@ SEASTAR_THREAD_TEST_CASE(multiple_outstanding_operations_on_failing_connection)
|
||||
mylog.trace("multiple_outstanding_operations_on_failing_connection");
|
||||
with_ldap_connection(local_fail_inject_address, [] (ldap_connection& c) {
|
||||
mylog.trace("multiple_outstanding_operations_on_failing_connection: invoking bind");
|
||||
bind(c).handle_exception(&ignore).get();;
|
||||
bind(c).handle_exception(&ignore).get();
|
||||
|
||||
std::vector<future<ldap_msg_ptr>> results_base;
|
||||
for (size_t i = 0; i < 10; ++i) {
|
||||
@@ -291,3 +291,31 @@ SEASTAR_THREAD_TEST_CASE(severed_connection_yields_exceptional_future) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Requires ASAN or valgrind to reliably detect the double-free.
|
||||
SEASTAR_THREAD_TEST_CASE(unregistered_msgid_double_free) {
|
||||
set_defbase();
|
||||
with_ldap_connection(local_ldap_address, [] (ldap_connection& c) {
|
||||
const auto bind_res = bind(c).get();
|
||||
BOOST_REQUIRE_EQUAL(LDAP_RES_BIND, ldap_msgtype(bind_res.get()));
|
||||
|
||||
// Bypass the public API to send a search without registering its
|
||||
// message ID, so poll_results() hits the unregistered-ID branch.
|
||||
int msgid = -1;
|
||||
const int rc = ldap_search_ext(c.get_ldap(), const_cast<char*>(base_dn), LDAP_SCOPE_SUBTREE,
|
||||
/*filter=*/nullptr,
|
||||
/*attrs=*/nullptr,
|
||||
/*attrsonly=*/0,
|
||||
/*serverctrls=*/nullptr,
|
||||
/*clientctrls=*/nullptr,
|
||||
/*timeout=*/nullptr,
|
||||
/*sizelimit=*/0, &msgid);
|
||||
BOOST_REQUIRE_EQUAL(LDAP_SUCCESS, rc);
|
||||
BOOST_REQUIRE_NE(-1, msgid);
|
||||
|
||||
// A public-API search forces poll_results() to process the
|
||||
// unregistered response before returning.
|
||||
const auto dummy = search(c, base_dn).get();
|
||||
BOOST_REQUIRE(dummy.get());
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user