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(a)openldap.org
Reporter: thetrenshow157(a)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)
--
You are receiving this mail because:
You are on the CC list for the issue.
https://bugs.openldap.org/show_bug.cgi?id=10573
Issue ID: 10573
Summary: OpenLDAP 2.7.0 fails to build with MSVC when
preprocessing symbol version maps
Product: OpenLDAP
Version: 2.7.0
Hardware: All
OS: Windows
Status: UNCONFIRMED
Keywords: needs_review
Severity: normal
Priority: ---
Component: build
Assignee: bugs(a)openldap.org
Reporter: openldap-msvc-673e3a64ee4f43(a)emalupe.com
Target Milestone: ---
OpenLDAP 2.7.0 fails to build with MSVC while generating the liblber symbol
version map. The regression appears to have been introduced by commit
8651f98a08c37bea6ee9be78acececd52bac66a0 (ITS#9739).
The new rules in libraries/liblber/Makefile.in and
libraries/libldap/Makefile.in invoke:
$(CPP) -x c -o $@ $(LT_CPPFLAGS) $(srcdir)/$(SYMBOL_VERSION_SCRIPT).in
The -x c option is specific to GCC/Clang. When Autoconf's configured C
preprocessor is MSVC (cl -E), cl ignores -x and treats the following c as an
input filename:
cl : Command line warning D9002 : ignoring unknown option '-x'
c1: fatal error C1083: Cannot open source file: 'c': No such file or
directory
make[2]: *** [Makefile:301: lber.map] Error 2
This was reproduced with OpenLDAP 2.7.0 and Visual Studio 2026/MSVC 14.51 on
Windows. OpenLDAP 2.6.13 builds successfully with the same compiler setup
because it does not preprocess these map files.
The same non-portable invocation is present in both the liblber and libldap
map-generation rules and remains in the current OPENLDAP_REL_ENG_2_7 and master
branches.
Could the hard-coded compiler language option be removed or replaced with a
configure-detected, compiler-portable way to preprocess the .map.in files?
--
You are receiving this mail because:
You are on the CC list for the issue.
https://bugs.openldap.org/show_bug.cgi?id=10563
Issue ID: 10563
Summary: ldap_count_message() returns '1' even with empty
LDAPMessage as input.
Product: OpenLDAP
Version: 2.6.13
Hardware: All
OS: All
Status: UNCONFIRMED
Keywords: needs_review
Severity: normal
Priority: ---
Component: libraries
Assignee: bugs(a)openldap.org
Reporter: feh(a)fehcom.de
Target Milestone: ---
Source: libldap/messages.c
The function
int ldap_count_messages( LDAP *ld, LDAPMessage *chain )
given *chain is NULL will return a '1' as result.
Line numbers included:
49 int
50 ldap_count_messages( LDAP *ld, LDAPMessage *chain )
51 {
52 int i;
53
54 assert( ld != NULL );
55 assert( LDAP_VALID( ld ) );
56
57 for ( i = 0; chain != NULL; chain = chain->lm_chain ) {
58 i++;
59 }
60
61 return( i );
62 }
It would be sufficient to test the LDAP message *chain in the following way
before the for loop is executed:
line 56: if (!chain && !*chain) return ( 0 );
--eh.
--
You are receiving this mail because:
You are on the CC list for the issue.
https://bugs.openldap.org/show_bug.cgi?id=10576
Issue ID: 10576
Summary: modify dn is not logged when STATS2 is on
Product: OpenLDAP
Version: 2.7.0
Hardware: All
OS: All
Status: UNCONFIRMED
Keywords: needs_review
Severity: normal
Priority: ---
Component: slapd
Assignee: bugs(a)openldap.org
Reporter: ondra(a)mistotebe.net
Target Milestone: ---
ITS#9042 hid the line in the else branch, it should be outside the if with a
STATS|STATS2 filter.
--
You are receiving this mail because:
You are on the CC list for the issue.
https://bugs.openldap.org/show_bug.cgi?id=10574
Issue ID: 10574
Summary: request_process can desync
Product: OpenLDAP
Version: 2.6.14
Hardware: All
OS: All
Status: UNCONFIRMED
Keywords: needs_review
Severity: normal
Priority: ---
Component: lloadd
Assignee: bugs(a)openldap.org
Reporter: ondra(a)mistotebe.net
Target Milestone: ---
Failing to allocate an upstream on a "write" tagged op, c_restricted_inflight
is not incremented but o_restricted still claims op's cone of focus is WRITE,
freeing that op then decrements counter spuriously. We need to reset
o_restricted if we didn't commit the restrictions on the rejection paths.
Related to ITS#10510, which only closed one half of the issue.
--
You are receiving this mail because:
You are on the CC list for the issue.
https://bugs.openldap.org/show_bug.cgi?id=10561
Issue ID: 10561
Summary: multiple logging.c minor issues
Product: OpenLDAP
Version: 2.6.13
Hardware: All
OS: All
Status: UNCONFIRMED
Keywords: needs_review
Severity: normal
Priority: ---
Component: slapd
Assignee: bugs(a)openldap.org
Reporter: dontbugme.relocate646(a)slmail.me
Target Milestone: ---
Created attachment 1185
--> https://bugs.openldap.org/attachment.cgi?id=1185&action=edit
servers/slapd/logging.c surprising behaviors
# OpenLDAP `slapd` log-file engine — observed bugs and pitfalls
This document lists defects and surprising behaviors identified by reading
`servers/slapd/logging.c` (the `logfile`, `logfile-format`, `logfile-only`
and `logfile-rotate` implementation) in this tree. All line references point to
that file.
> Scope: these concern the **internal** log file that `slapd` writes itself when
> `logfile <path>` is configured. They are independent of `rsyslogd`/`syslog-ng`.
---
## Bug 1 — `loglevel`/`olcLogLevel` messages are *not* written to the logfile
unless `logfile-only on`
### What happens
`slapd` maintains two separate diagnostic streams:
* the **debug stream** (`slap_debug`), fed by the `-d` command-line flag, and
* the **syslog stream** (`ldap_syslog`), fed by `loglevel`/`olcLogLevel` (and
`-s`).
The internal log file is written **only** from the debug stream. The actual
write is done in `slap_debug_print()`, which is the `LBER_OPT_LOG_PRINT_FN`
callback fired for every `ber_log*` message whose level passes `slap_debug`
(`logging.c:138` and `:222`). Messages that only pass `ldap_syslog` are emitted
through `syslog()` and never reach the file.
`logfile-only` controls this:
* `logfile-only off` (default): `slap_debug_print()` also writes to stderr
(`:135`), and syslog messages stay in syslog — **they never land in the
file**.
* `logfile-only on`: `slap_syslog_set()` ORs the syslog level into `slap_debug`
and zeroes `ldap_syslog` (`:571-581`, `:807-819`, `:593-600`), so syslog
messages now flow into the file — **but syslog itself is disabled**.
So there is **no configuration that writes *both* syslog and a complete log
file**. Setting `logfile` + `loglevel stats` is the trap most operators fall
into: stats go to syslog, and the file stays empty (unless you also used `-d`
or `logfile-only on`).
### How to reproduce
`slapd.conf` (or `cn=config` equivalent):
```
logfile /tmp/slapd.log
loglevel stats
# (no -d flag, no logfile-only)
```
1. Start `slapd -f slapd.conf -h "ldap://:3899/"` (do **not** pass `-d`).
2. Bind / search a few times.
3. Inspect the file:
```sh
cat /tmp/slapd.log # empty (or only the startup Versionstr line)
journalctl -t slapd # shows "conn=N op=M ... RESULT" stats lines
```
4. Stop, add `logfile-only on`, restart, repeat. Now:
```sh
cat /tmp/slapd.log # stats lines ARE present
journalctl -t slapd # stats lines are GONE (syslog disabled)
```
### Severity
High for operators expecting `logfile` + `loglevel` to mirror syslog. The
behavior is by design but undocumented as a limitation.
---
## Bug 2 — Stale PID in syslog-style log prefixes (`getpid()` captured before
`fork()`)
### What happens
When `logfile-format` is one of the syslog-style values
(`syslog-utc`/`syslog-localtime`/`rfc3339-utc`), the prefix string
`"<host> <prog>[<pid>]: "` is built **once**, at config-parse time, inside the
`CFG_LOGFILE_FORMAT` handler (`logging.c:852-856`):
```c
splen = sprintf( syslog_prefix, "%s %s %s[%d]: ", ..., serverName, getpid() );
```
`config_logging()` runs while `slapd` is still the original process. `slapd`
then daemonizes (`slapd_daemon()` forks), so the child that actually does the
logging has a **different PID** than the one baked into `syslog_prefix`.
Every line in the file therefore shows the pre-fork parent PID, not the PID of
the running daemon.
### How to reproduce
`slapd.conf`:
```
logfile /tmp/slapd.log
logfile-format syslog-localtime
loglevel stats
```
1. Start `slapd` in daemon mode (default): `slapd -f slapd.conf -h
"ldap://:3899/"`.
2. Find the real daemon PID:
```sh
pidof slapd
cat /run/slapd/slapd.pid # or wherever pidfile points
```
3. Trigger a line (any search) and look at the prefix in the file:
```sh
head -3 /tmp/slapd.log
# e.g. Aug 05 10:40:12 host slapd[1234]: conn=1 ...
```
`1234` is the PID of the short-lived parent, not the daemon PID printed by
`pidof slapd`.
### Severity
Medium. Cosmetic for single-instance setups, but misleading for log analysis /
process correlation and for systems that run `slapd` under a supervisor that
expects the logged PID to match the supervised process.
---
## Bug 3 — `logfile-format default` is identical to `logfile-format debug`
### What happens
The log-file header is only rebuilt when `logfile_format > LFMT_DEBUG`
(`logging.c:185`). For `LFMT_DEFAULT` (value `0`) and `LFMT_DEBUG` (value `1`)
the `iov[0]` debug prefix (`"%lx.<frac> <pthread> "`, built at `:130`) is used
verbatim. So:
* `default` → raw `epoch.hex <threadptr> ` prefix, **no** date, **no**
hostname,
**no** PID;
* `debug` → exactly the same.
The name `default` suggests a "normal" syslog-like line, but it is just the
`-d`-style debugging prefix. The only formats that actually add a timestamp /
host / PID header are `syslog-utc`, `syslog-localtime` and `rfc3339-utc`.
### How to reproduce
```
logfile /tmp/default.log
logfile-format default
loglevel stats
# (separate run)
logfile /tmp/debug.log
logfile-format debug
loglevel stats
```
Run `slapd`, trigger one operation in each, then `diff`:
```sh
head -1 /tmp/default.log; head -1 /tmp/debug.log # byte-identical prefixes
```
### Severity
Low. Documentation/naming clarity issue; can surprise anyone expecting
human-readable timestamps from the default format.
---
## Bug 4 — Rotation numbered-shift runs outside the mutex (lost backups under
load)
### What happens
Rotation is split in two:
1. Under `logfile_mutex` (`:140-183`): the current file is renamed to
`<path>.tmp` (`:147-148`) and a fresh file is reopened (`:166`).
2. **After** the mutex is released (`:227`), the numbered-shift loop runs
(`:229-238`): it renames `<path>.tmp` → `<path>.NN` and shifts older
`<path>.NN` → `<path>.N(N+1)`.
Because step 2 executes outside the lock, two (or more) threads that both
tripped the size/age threshold can interleave:
```
T1: under lock -> rename current -> .tmp ; reopen ; unlock
T2: under lock -> rename NEW current -> .tmp ; reopen ; unlock
T1: outside lock-> rename .tmp -> .NN (this .tmp is actually T2's rotated
file)
T2: outside lock-> rename .tmp -> .NN (no .tmp exists anymore -> rename()
fails,
the backup T2 meant to keep is lost)
```
Consequences under heavy concurrent logging near the rotation threshold:
* a rotated backup can be silently overwritten / lost, and
* `rename()` is called on a `.tmp` that no longer exists (returns `-1`,
ignored).
The trigger-to-`.tmp` step is safe (under the lock) but the hand-off to the
outside-lock shift is racy because the shared `.tmp` name is reused by every
rotation event.
### How to reproduce (best-effort, not deterministic)
```
logfile /tmp/slapd.log
logfile-format debug
logfile-rotate 5 1 0 # 5 backups, 1 MB size limit, no age limit
loglevel any # enable verbose categories
```
Drive a very high-volume debug stream so the file crosses 1 MB repeatedly in a
short window (e.g. `loglevel sync stats packets` plus a busy replication
session, or a tight loop of anonymous binds). Then list backups:
```sh
ls -la /tmp/slapd.log*
```
Expected: `.01` … `.05` present and strictly ordered by age.
Observed under load: gaps (e.g. `.01 .02 .04 .05` with `.03` missing) or a
rotation where the oldest retained copy is newer than it should be, indicating
a backup was clobbered by a racing rotation.
> Note: because the race is timing-dependent, run the load several times; the
> failure is intermittent, which is itself the signature of a lock-ordering bug.
### Severity
Low-to-medium. Only matters with `logfile-rotate` enabled and very high log
volume. Data-loss is of rotated *backups*, not of the live log.
---
## Bug 5 — Age-based rotation uses inode change time, not file create/modify
time
### What happens
When a file is (re)opened, the rotation "birth" timestamp is taken from
`st_ctime` (`logging.c:287`):
```c
logfile_fcreated = st.st_ctime; /* not strictly true but close enough */
```
The comment admits the approximation. `st_ctime` changes on *any* inode
metadata change (chmod, chown, rename, truncate, `touch -c`), not just content
creation. Age-based rotation (`logfile-rotate <max> <MB> <hours>`) therefore
measures the interval since the last inode-changing event, which can be reset
by an external tool (logrotate `copytruncate`, backup, permission change) and
produce an unexpectedly early or late rotation.
### How to reproduce
```
logfile /tmp/slapd.log
logfile-format debug
logfile-rotate 3 0 1 # rotate every 1 hour (no size limit)
loglevel stats
```
1. Start `slapd`; note the time.
2. Before the hour elapses, touch the inode metadata externally:
```sh
touch /tmp/slapd.log # updates ctime (open with O_TRUNC not needed)
```
3. Watch rotation: it can fire based on the *touch* time rather than the
daemon's own start/last-write time, because `logfile_fcreated` reflects
`ctime`.
### Severity
Low. Edge-case affecting operators who let an external tool also touch the
logfile.
---
## Summary table
| # | Bug | Config affected | Effect | Can lose data? |
|---|-----|-----------------|--------|----------------|
| 1 | `loglevel` not written to file unless `logfile-only on` |
`logfile`+`loglevel` | file misses syslog-level messages | no (silent gap) |
| 2 | Stale PID in syslog-style prefixes | `logfile-format
syslog-*`/`rfc3339-*` | wrong `[pid]` in every line | no |
| 3 | `default` == `debug` output | `logfile-format default` | no
timestamp/host/pid header | no |
| 4 | Rotation shift outside mutex | `logfile-rotate` under load |
lost/overwritten backups | yes (backups only) |
| 5 | Age rotation uses `ctime` | `logfile-rotate … <hours>` | wrong rotation
timing | no |
---
## Workarounds
* To get `loglevel` content in the file, use `logfile-only on` **and** accept
that native syslog logging is then disabled — or run `slapd -d <level>`
instead of `loglevel`, or keep `rsyslogd` as the file writer.
* For correct per-line PID/timestamps, prefer `logfile-format rfc3339-utc`
(still has the stale-PID issue from Bug 2, but at least a real timestamp).
* Avoid relying on `logfile-rotate` for audit-grade retention under very high
log volume; use an external log rotator that copies and truncates, or pipe to
`rsyslogd`.
--
You are receiving this mail because:
You are on the CC list for the issue.
https://bugs.openldap.org/show_bug.cgi?id=10571
Issue ID: 10571
Summary: Asyncmeta's conn-ttl optional reset-interval argument
silently defaults to the TTL
Product: OpenLDAP
Version: 2.7.0
Hardware: All
OS: All
Status: UNCONFIRMED
Keywords: needs_review
Severity: normal
Priority: ---
Component: backends
Assignee: bugs(a)openldap.org
Reporter: ondra(a)mistotebe.net
Target Milestone: ---
mc->mc_conn_reset_interval is set to TTL if the 1 argument form is configured
(no value for <interval> provided) but as per manpage it should default to `1`
instead.
--
You are receiving this mail because:
You are on the CC list for the issue.
https://bugs.openldap.org/show_bug.cgi?id=10568
Issue ID: 10568
Summary: Client tools segfault when run without arguments
Product: OpenLDAP
Version: 2.7.0
Hardware: x86_64
OS: Linux
Status: UNCONFIRMED
Keywords: needs_review
Severity: normal
Priority: ---
Component: client tools
Assignee: bugs(a)openldap.org
Reporter: nzb_tuxxx(a)proton.me
Target Milestone: ---
When the default connection fails, several client tools call `strlen(ldapuri)`
while `ldapuri` is `NULL`.
Steps to reproduce:
1. Run `ldapadd`, `ldapdelete`, `ldapmodify`, `ldapmodrdn`, `ldappasswd`,
`ldapsearch`, `ldapvc`, or `ldapwhoami` without arguments.
2. Observe `Segmentation fault (core dumped)` and exit status 139.
References:
- Regression:
https://git.openldap.org/openldap/openldap/-/commit/37d677fb8d16b05a387c9f9…
- Downstream report:
https://gitlab.archlinux.org/archlinux/packaging/packages/openldap/-/work_i…
--
You are receiving this mail because:
You are on the CC list for the issue.
https://bugs.openldap.org/show_bug.cgi?id=10564
--- Comment #3 from Quanah Gibson-Mount <quanah(a)openldap.org> ---
head:
• 4846d7e3
by Howard Chu at 2026-08-10T16:36:31+01:00
ITS#10564 slapo-sssvlv: tighten sss_parseCtrl
RE27:
• f92a2e17
by Howard Chu at 2026-08-20T21:02:57+00:00
ITS#10564 slapo-sssvlv: tighten sss_parseCtrl
RE26:
• 6c0323aa
by Howard Chu at 2026-08-20T21:07:39+00:00
ITS#10564 slapo-sssvlv: tighten sss_parseCtrl
--
You are receiving this mail because:
You are on the CC list for the issue.
https://bugs.openldap.org/show_bug.cgi?id=10575
Issue ID: 10575
Summary: MDB_WRITEMAP commit fails on Windows without
MDB_NOSYNC on 1.0.1
Product: LMDB
Version: 1.0.1
Hardware: x86_64
OS: Windows
Status: UNCONFIRMED
Keywords: needs_review
Severity: normal
Priority: ---
Component: liblmdb
Assignee: bugs(a)openldap.org
Reporter: github(a)nicwatson.org
Target Milestone: ---
Created attachment 1194
--> https://bugs.openldap.org/attachment.cgi?id=1194&action=edit
reproducer
On Windows, an environment opened with MDB_WRITEMAP cannot commit a write
transaction unless MDB_NOSYNC or MDB_NOMETASYNC is also set. mdb_txn_commit()
fails with ERROR_INVALID_HANDLE.
See attached for reproducer.
This does not impact Linux, MacOS, or the .9.* series.
--
You are receiving this mail because:
You are on the CC list for the issue.