From robert@fledge.watson.org  Sun Aug 10 15:02:59 2003
Return-Path: <robert@fledge.watson.org>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id D9E3937B404
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 10 Aug 2003 15:02:59 -0700 (PDT)
Received: from fledge.watson.org (fledge.watson.org [204.156.12.50])
	by mx1.FreeBSD.org (Postfix) with ESMTP id D5FDB43FAF
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 10 Aug 2003 15:02:58 -0700 (PDT)
	(envelope-from robert@fledge.watson.org)
Received: from fledge.watson.org (localhost [127.0.0.1])
	by fledge.watson.org (8.12.9/8.12.9) with ESMTP id h7AM2eAL090297
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 10 Aug 2003 18:02:40 -0400 (EDT)
	(envelope-from robert@fledge.watson.org)
Received: (from robert@localhost)
	by fledge.watson.org (8.12.9/8.12.9/Submit) id h7AM2eLG090296;
	Sun, 10 Aug 2003 18:02:40 -0400 (EDT)
Message-Id: <200308102202.h7AM2eLG090296@fledge.watson.org>
Date: Sun, 10 Aug 2003 18:02:40 -0400 (EDT)
From: Robert Watson <rwatson@freebsd.org>
Reply-To: Robert Watson <rwatson@freebsd.org>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: dbm_nextkey() misbehaves after dbm_store() in dbm(3)
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         55448
>Category:       kern
>Synopsis:       dbm(3): dbm_nextkey() misbehaves after dbm_store() in dbm(3)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Aug 10 15:10:16 PDT 2003
>Closed-Date:    
>Last-Modified:  Tue Apr 21 00:03:01 UTC 2009
>Originator:     Robert Watson
>Release:        FreeBSD 4.8-STABLE i386
>Organization:
>Environment:
System: FreeBSD fledge.watson.org 4.8-STABLE FreeBSD 4.8-STABLE #4: Mon Aug 4 00:26:28 EDT 2003 robert@fledge.watson.org:/home/data/obj/home/data/fbsd-stable/src/sys/FLEDGE i386

>Description:

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.

>How-To-Repeat:

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. */
			break;
		case sizeof(id):
			id = *(struct ipdata *)data.dptr;
			break;
		default:
			/* panic */
		}
		/* Perform data updates. */
		data.dptr = (void *)&id;
		data.dsize = sizeof(id);

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

		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.  
>Fix:
>Release-Note:
>Audit-Trail:

From: Robert Watson <rwatson@freebsd.org>
To: FreeBSD-gnats-submit@freebsd.org
Cc:  
Subject: Re: bin/55448: dbm_nextkey() misbehaves after dbm_store() in dbm(3)
Date: Sun, 10 Aug 2003 18:13:04 -0400 (EDT)

 Just as a follow-up to justify the desire for this behavior to work: in
 order to change the size of all fields in a database, working around this
 bug currently seems to require rescanning the database O(n) each time by
 restarting the search as soon as a record is resized, meaning that the
 operation takes O(n^2) to complete.  It would be nice to avoid this.
 
 Robert N M Watson             FreeBSD Core Team, TrustedBSD Projects
 robert@fledge.watson.org      Network Associates Laboratories
 
>Unformatted:
