This is a double-free vulnerability in 389-ds-base's LDAP control handling, triggered specifically when rejecting a critical Session Tracking control. The flaw sits in the rejection path: when the server rejects an unsupported critical control, it frees the control array but leaves the SLAPI_REQCONTROLS slot in the operation's pblock populated. If the operation then proceeds through its normal teardown sequence, that slot gets freed again — triggering the double-free. The vulnerability is unauthenticated and triggers with a single LDAP request, making it trivially exploitable at scale.
The root cause isn't a single developer mistake — it's a structural flaw in how 389-ds-base handles request context. The pblock is a shared state object with implicit ownership semantics that the API doesn't enforce. When adding new controls, developers reason locally about the control logic but rarely trace all call sites that might later read from SLAPI_REQCONTROLS during teardown. This is a distributed cleanup problem masquerading as a feature bug.
This is not an isolated incident. The same double-free-in-rejection-path pattern has appeared in OpenLDAP, Sun DSEE, and twice before in 389-ds-base (CVE-2016-5414 for EXOP controls, CVE-2018-1089 for Password Policy controls). Each prior fix was scoped narrowly to the triggering control rather than auditing the entire rejection-cleanup contract. Session Tracking, as a rarely-used diagnostic control, sat in the codebase for years with minimal scrutiny — exactly the conditions where implicit contracts erode.
For defenders: prioritize patching this immediately given the unauthenticated trigger and trivial exploitability. Beyond patching, audit your own deployments for other rarely-used controls (ManageDsaIT, Subentries, Permissive Modify, X.500 artifacts) — if this pattern recurs predictably across the control surface, at least one other rejection path likely has the same cleanup gap. Request that your vendor or internal teams audit the control rejection paths comprehensively rather than accepting per-control patches. The structural fix requires making pblock ownership explicit in the API, which is a codebase-level effort, not a one-CVE fix.