I reproduced the problem with valgrind and debug symbols. The output is likely helpful for anyone interested in tracking down this issue. This is sid i386, slapd version 2.4.28-1.1, gnutls version 2.12.16-1.
==9140== Memcheck, a memory error detector ==9140== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al. ==9140== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info ==9140== Command: slapd ==9140== ==9140== Invalid free() / delete / delete[] / realloc() ==9140== at 0x71FC40C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==9140== by 0x74D87AD: gnutls_priority_deinit (gnutls_priority.c:804) ==9140== by 0x7249A4A: tlsg_ctx_free (in /usr/lib/i386-linux-gnu/libldap_r-2.4.so.2.8.1) ==9140== by 0x72461D2: ldap_pvt_tls_ctx_free (in /usr/lib/i386-linux-gnu/libldap_r-2.4.so.2.8.1) ==9140== by 0x77D3E15: (below main) (libc-start.c:228) ==9140== Address 0x7f2dd88 is 0 bytes inside a block of size 492 free'd ==9140== at 0x71FC40C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==9140== by 0x74D8549: gnutls_priority_init (gnutls_priority.c:789) ==9140== by 0x7248CEB: tlsg_ctx_init (in /usr/lib/i386-linux-gnu/libldap_r-2.4.so.2.8.1) ==9140== by 0x7EBDB07: ??? ==9140== ==9140== ==9140== HEAP SUMMARY: ==9140== in use at exit: 4,114 bytes in 64 blocks ==9140== total heap usage: 13,850 allocs, 13,787 frees, 777,536 bytes allocated ==9140== ==9140== 31 bytes in 1 blocks are definitely lost in loss record 11 of 21 ==9140== at 0x71FD208: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==9140== by 0x19829A: ??? (in /usr/sbin/slapd) ==9140== by 0x74A681E: sasl_server_init (in /usr/lib/i386-linux-gnu/libsasl2.so.2.0.25) ==9140== by 0x19A211: slap_sasl_init (in /usr/sbin/slapd) ==9140== by 0x1718BC: slap_init (in /usr/sbin/slapd) ==9140== by 0x11DE46: main (in /usr/sbin/slapd) ==9140== ==9140== 492 bytes in 1 blocks are definitely lost in loss record 18 of 21 ==9140== at 0x71FB986: calloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==9140== by 0x74D787B: gnutls_priority_init (gnutls_priority.c:535) ==9140== by 0x77D3E15: (below main) (libc-start.c:228) ==9140== ==9140== LEAK SUMMARY: ==9140== definitely lost: 523 bytes in 2 blocks ==9140== indirectly lost: 0 bytes in 0 blocks ==9140== possibly lost: 0 bytes in 0 blocks ==9140== still reachable: 3,591 bytes in 62 blocks ==9140== suppressed: 0 bytes in 0 blocks ==9140== Reachable blocks (those to which a pointer was found) are not shown. ==9140== To see them, rerun with: --leak-check=full --show-reachable=yes ==9140== ==9140== For counts of detected and suppressed errors, rerun with: -v ==9140== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 103 from 14) Some line are still missing. As a first step let me first deduce them: gnutls_priority_deinit is called from tlsg_ctx_free in libraries/libldap/tls_g.c:275. gnutls_priority_init is indirectly called from tlsg_ctx_init. The only possible direct callers are tlsg_parse_ciphers and tlsg_ctx_new. Only tlsg_parse_ciphers is called from tlsg_ctx_init. tlsg_ctx_init calls tlsg_parse_ciphers in libraries/libldap/tls_g.c:318 tlsg_parse_ciphers calls gnutls_priority_init in libraries/libldap/tls_g.c:793 The next step is to deduce what actually happens. 1) (chronological) first free. Since gnutls_priority_init frees the priority cache it the return value is GNUTLS_E_INVALID_REQUEST != 0. (lib/gnutls_priority.c:791) Thus tlsg_parse_ciphers also returns non-zero. (libraries/libldap/tls_g.c:793) Since tlsg_parse_ciphers is called (libraries/libldap/tls_g.c:318) lo->ldo_tls_ciphersuite is non-zero. So the error branch is taken. Another hint for the error branch is the error message "TLS: could not set cipher list TLSv1." output on stdout (with -d..). So the tlsg_ctx_init call returns -1. (libraries/libldap/tls_g.c:322) 2) (chronological) second free. ldap_pvt_tls_ctx_free calls tlsg_ctx_free via a member function table in libraries/libldap/tls2.c:79. tlsg_ctx_free calls gnutls_priority_deinit in libraries/libldap/tls_g.c:275. gnutls_priority_deinit then (double) frees the priority cache in lib/gnutls_priority.c:804. I would say that this is not a gnutls bug, because gnutls_priority_init returned non-zero and thus gnutls_priority_deinit must not be called. So how are these ldap tls objects initialized? As we have seen above (in the second free) a member function table is used. A bit of grepping reveals the actual initialization in libraries/libldap/tls2.c:232 and following. Aparently a ldap tls object is initialized by first calling *_ctx_new and then *_ctx_init. So tlsg_ctx_new is likely called before tlsg_ctx_init and initializes the priority cache in libraries/libldap/tls_g.c:243. Note that the return value of gnutls_priority_init is *not* checked (bug #1). It is unlikely to fail due to the fixed and known-good priority string, but it still could fail (e.g. malloc fail). Then tlsg_parse_ciphers re-initializes the priority cache. This is a memory leak (bug #2, can also be seen in the valgrind output). Even though this re-initialization is checked, it is later double-freed (bug #3). Maybe someone with more insight into the code can fix the issue? Helmut -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org