[Date Prev][Date Next] [Chronological] [Thread] [Top]

slapd crash in attr_delete() with simple SLAPI plugin



Hi,

I'm trying to write a simple SLAPI plugin (see attached file) that computes 
the "gecos" attribute in a posixAccount entry from other attributes in the 
same entry (cn,telephoneNumber, etc.).

My first question is: has this already been done, or is there a simpler way to 
do it? I couldn't find anything, which seems a little surprising.

My second question is: why does my plugin work for some entries but segfault 
on others? The crash always occurs inside slapi_entry_attr_set_charptr() when 
it calls attr_delete(). It seems the heap is corrupted somehow... note, I've 
tried taking out the calls to slapi_ch_free() (worried that I was 
double-freeing or corrupting memory somehow) but the result is the same.

In my test database I have one entry for which this plugin works, and many for 
which it doesn't. I can reliably retrieve search results for the working 
entry, and reliably crash the server the very first time I try to retrieve 
any of the other entries. Both working and crashing entries only have some of 
the attributes used to construct the full gecos field. The plugin also works 
correctly for entries that don't have a gecos attribute (ie. returns them 
unmodified).

Please see the backtrace below... and let me know if I can provide any more 
details. This is with slapd from OpenLDAP-2.3.7 running on x86 Linux, 
compiled with GCC 3.3.5.

Andrew

Core was generated by `/home/andrewb/local/lib/slapd -h 
ldap://localhost:9009'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /home/andrewb/local/lib/libldap_r-2.3.so.0...done.
Loaded symbols for /home/andrewb/local/lib/libldap_r-2.3.so.0
Reading symbols from /home/andrewb/local/lib/liblber-2.3.so.0...done.
Loaded symbols for /home/andrewb/local/lib/liblber-2.3.so.0
Reading symbols from /usr/lib/libiodbc.so.2...done.
Loaded symbols for /usr/lib/libiodbc.so.2
Reading symbols from /usr/lib/libiodbcinst.so.2...done.
Loaded symbols for /usr/lib/libiodbcinst.so.2
Reading symbols from /usr/lib/libslp.so.1...done.
Loaded symbols for /usr/lib/libslp.so.1
Reading symbols from /lib/libm.so.6...done.
Loaded symbols for /lib/libm.so.6
Reading symbols from /lib/libnsl.so.1...done.
Loaded symbols for /lib/libnsl.so.1
Reading symbols from /usr/lib/libsasl2.so.2...done.
Loaded symbols for /usr/lib/libsasl2.so.2
Reading symbols from /usr/lib/i686/cmov/libssl.so.0.9.7...done.
Loaded symbols for /usr/lib/i686/cmov/libssl.so.0.9.7
Reading symbols from /usr/lib/i686/cmov/libcrypto.so.0.9.7...done.
Loaded symbols for /usr/lib/i686/cmov/libcrypto.so.0.9.7
Reading symbols from /lib/libcrypt.so.1...done.
Loaded symbols for /lib/libcrypt.so.1
Reading symbols from /lib/libresolv.so.2...done.
Loaded symbols for /lib/libresolv.so.2
Reading symbols from /usr/lib/libltdl.so.3...done.
Loaded symbols for /usr/lib/libltdl.so.3
Reading symbols from /lib/libdl.so.2...done.
Loaded symbols for /lib/libdl.so.2
Reading symbols from /lib/libwrap.so.0...done.
Loaded symbols for /lib/libwrap.so.0
Reading symbols from /lib/libpthread.so.0...done.
Loaded symbols for /lib/libpthread.so.0
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Reading symbols from /lib/libnss_files.so.2...done.
Loaded symbols for /lib/libnss_files.so.2
Reading symbols from /usr/lib/sasl2/libsasldb.so.2...done.
Loaded symbols for /usr/lib/sasl2/libsasldb.so.2
Reading symbols from /usr/lib/libdb-4.2.so...done.
Loaded symbols for /usr/lib/libdb-4.2.so
Reading symbols from /usr/lib/sasl2/libcrammd5.so.2...done.
Loaded symbols for /usr/lib/sasl2/libcrammd5.so.2
Reading symbols from /usr/lib/sasl2/libdigestmd5.so.2...done.
Loaded symbols for /usr/lib/sasl2/libdigestmd5.so.2
Reading symbols from /usr/lib/sasl2/libotp.so.2...done.
Loaded symbols for /usr/lib/sasl2/libotp.so.2
Reading symbols from /usr/lib/sasl2/libanonymous.so.2...done.
Loaded symbols for /usr/lib/sasl2/libanonymous.so.2
Reading symbols from /usr/lib/sasl2/libplain.so.2...done.
Loaded symbols for /usr/lib/sasl2/libplain.so.2
Reading symbols from /usr/lib/sasl2/liblogin.so.2...done.
Loaded symbols for /usr/lib/sasl2/liblogin.so.2
Reading symbols from /usr/lib/sasl2/libntlm.so.2...done.
Loaded symbols for /usr/lib/sasl2/libntlm.so.2
Reading symbols from /home/andrewb/local/lib/ldap/back_bdb-2.3.so.0...done.
Loaded symbols for /home/andrewb/local/lib/ldap/back_bdb-2.3.so.0
Reading symbols from /usr/lib/libldap_r.so.2...done.
Loaded symbols for /usr/lib/libldap_r.so.2
Reading symbols from /usr/lib/liblber.so.2...done.
Loaded symbols for /usr/lib/liblber.so.2
Reading symbols from /usr/lib/libgnutls.so.11...done.
Loaded symbols for /usr/lib/libgnutls.so.11
Reading symbols from /usr/lib/libtasn1.so.2...done.
Loaded symbols for /usr/lib/libtasn1.so.2
Reading symbols from /usr/lib/libgcrypt.so.11...done.
Loaded symbols for /usr/lib/libgcrypt.so.11
Reading symbols from /usr/lib/libgpg-error.so.0...done.
Loaded symbols for /usr/lib/libgpg-error.so.0
Reading symbols from /usr/lib/libz.so.1...done.
Loaded symbols for /usr/lib/libz.so.1
Reading symbols from /home/andrewb/computed_gecos/computed_gecos.so...done.
Loaded symbols for /home/andrewb/computed_gecos/computed_gecos.so
#0  0x402a2b22 in pthread_mutex_lock () from /lib/libpthread.so.0
(gdb) bt
#0  0x402a2b22 in pthread_mutex_lock () from /lib/libpthread.so.0
#1  0x4035e17d in free () from /lib/libc.so.6
#2  0x40067cfd in ber_memfree_x (p=0x81fe672, ctx=0x0) at memory.c:154
#3  0x40068adf in ber_bvarray_free_x (a=0x81febc4, ctx=0x0) at memory.c:761
#4  0x40068b23 in ber_bvarray_free (a=0x81febc4) at memory.c:771
#5  0x080798f9 in attr_free ()
#6  0x0807a0df in attr_delete ()
#7  0x0811b995 in slapi_entry_attr_set_charptr ()
#8  0x4056dde6 in pre_entry () 
from /home/andrewb/computed_gecos/computed_gecos.so
#9  0x081147dd in slapi_int_call_plugins ()
#10 0x08125279 in slapi_int_init_object_extensions ()
#11 0x081252e2 in slapi_int_init_object_extensions ()
#12 0x08125909 in slapi_tag2op ()
#13 0x08081d9f in slap_send_search_entry ()
#14 0x40549f16 in bdb_search (op=0x81fc8c8, rs=0xbf5ff8c4) at search.c:873
#15 0x080d3773 in overlay_op_walk ()
#16 0x08125b8d in slapi_tag2op ()
#17 0x080d36fc in overlay_op_walk ()
#18 0x080d3919 in overlay_op_walk ()
#19 0x080d39ab in overlay_op_walk ()
#20 0x080732a8 in fe_op_search ()
#21 0x08072d98 in do_search ()
#22 0x08070424 in connection_done ()
#23 0x40023d39 in ldap_int_thread_pool_wrapper (xpool=0x8192b08) at 
tpool.c:487
#24 0x402a1e51 in pthread_start_thread () from /lib/libpthread.so.0
#25 0x403c492a in clone () from /lib/libc.so.6
/* SLAPI plugin to return a "gecos" attribute (as used by posixAccount)
 * computed from other attributes in the same entry.
 *
 * Andrew Baumann <andrewb@cse.unsw.edu.au>
 */

/* Format of the GECOS field in terms of LDAP attributes is:
 * cn,roomNumber,telephoneNumber,homePhone,mail
 * the last field is actually "other", an email address seems most useful
 */

#include <slapi-plugin.h>
#include <stdio.h>
#include <string.h>

#define GECOS_MAX_LEN 1024

#define FAIL_ON_ERROR(r, msg) 						\
	if (r != 0) {							\
		slapi_log_error(SLAPI_LOG_PLUGIN, __FUNCTION__, msg);	\
		return -1;						\
	}

static Slapi_PluginDesc
plugin_desc = {"computed_gecos", "ABsoft", "0.1", "computed GECOS attribute"};

/* called before an entry is returned to the client */
static int
pre_entry(Slapi_PBlock *pb)
{
	Slapi_Entry *entry;
	Slapi_Attr *attr;
	char *str, *cn, *roomNum, *telephoneNum, *homePhone, *mail;
	int r, len;

	/* get the entry being returned */
	r = slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &entry);
	FAIL_ON_ERROR(r, "get entry parameter");

	/* check if the entry contains the "gecos" attribute */
	if (entry == NULL || slapi_entry_attr_find(entry, "gecos", &attr) != 0)
		return 0;

	/* get the contents of the fields that make up the gecos string */
	cn = slapi_entry_attr_get_charptr(entry, "cn");
	roomNum = slapi_entry_attr_get_charptr(entry, "roomNumber");
	telephoneNum = slapi_entry_attr_get_charptr(entry, "telephoneNumber");
	homePhone = slapi_entry_attr_get_charptr(entry, "homePhone");
	mail = slapi_entry_attr_get_charptr(entry, "mail");

	/* construct the gecos string */
	str = slapi_ch_malloc(GECOS_MAX_LEN);
	len = snprintf(str, GECOS_MAX_LEN, "%s,%s,%s,%s,%s",
		       cn ? cn : "", roomNum ? roomNum : "",
		       telephoneNum ? telephoneNum : "",
		       homePhone ? homePhone : "", mail ? mail : "");

	if (len >= GECOS_MAX_LEN) {
		str[GECOS_MAX_LEN - 1] = '\0';
		slapi_log_error(SLAPI_LOG_PLUGIN, __FUNCTION__,
				"Warning: gecos attribute truncated");
	}

	/* set the gecos attribute, overwriting whatever was there */
	slapi_entry_attr_set_charptr(entry, "gecos", str);

	/* clean up (the SLAPI functions take copies) */
	slapi_ch_free((void **) &str);
	slapi_ch_free((void **) &cn);
	slapi_ch_free((void **) &roomNum);
	slapi_ch_free((void **) &telephoneNum);
	slapi_ch_free((void **) &homePhone);
	slapi_ch_free((void **) &mail);

	return 0;
}

int
computed_gecos_init(Slapi_PBlock *pb)
{
	int r;

	r = slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION,
			     SLAPI_PLUGIN_CURRENT_VERSION);
	FAIL_ON_ERROR(r, "setting plugin version");

	r = slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, &plugin_desc);
	FAIL_ON_ERROR(r, "setting plugin version");

	r = slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_ENTRY_FN, pre_entry);
	FAIL_ON_ERROR(r, "setting callback");

	return 0;
}