bin/55448: dbm_nextkey() misbehaves after dbm_store() in dbm(3)

Robert Watson rwatson at
Sun Aug 10 15:10:18 PDT 2003

>Number:         55448
>Category:       bin
>Synopsis:       dbm_nextkey() misbehaves after dbm_store() in dbm(3)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Aug 10 15:10:16 PDT 2003
>Originator:     Robert Watson
>Release:        FreeBSD 4.8-STABLE i386
System: FreeBSD 4.8-STABLE FreeBSD 4.8-STABLE #4: Mon Aug 4 00:26:28 EDT 2003 robert at i386


dbm(3) provides a simply database API based on db(3).  It appears to be
possible to create database corruption through the use of dbm_nextkey()
and dbm_store() in the event that an entry in the database undergoes
a size change.  In particular, if you perform a dbm_fetch() on a key
returned by dbm_nextkey(), and then dbm_store() a larger value than
the data returned by dbm_fetch(), the next return from dbm_query() may
point into the newly updated value of the previous entry.


We have a local DBM database with two types of entries: old entries that
have a data size of an int, and new entries, with a data size of two
ints.  During a sweep of the database, the software may decide to update
fields from the old entry type to the new entry.  Typically, this uses
the above-described sequence:

	struct ipdata {
		int	int1;
		int	int2;

	key = dbm_firstkey(dbm);
	while (key.dptr != NULL) {
		data = dbm_fetch(dbm, key);
		switch (data.dsize) {
		case sizeof(int):
			/* fake up the new structure. */
		case sizeof(id):
			id = *(struct ipdata *)data.dptr;
			/* panic */
		/* Perform data updates. */
		data.dptr = (void *)&id;
		data.dsize = sizeof(id);

		if (dbm_store(dbm, key, data, DBM_REPLACE) == -1)

		key = dbm_nextkey(dbm);

When an entry is upgraded, the next call to dbm_nextkey() returns the
second int in the new ipdata structure written, rather than the next
field, suggesting that the iterator isn't updated for write changes to
the database.  

More information about the freebsd-bugs mailing list