Consider how a keyblock is updated when using a keyring:
hd = keydb_new (); keydb_search (hd, ...); hd->found.offset = offset of matching keyblock keydb_update_keyblock (hd, keyblock); lock_all (hd); keyring_update_keyblock (hd, keyblock); replace block starting at hd->found.offset with the new keyblock unlock_all (hd);
The main problem is that we have a time of check to time of use (TOCTTOU) bug:
we don't look up the offset while we have the lock so another process could have
come along and modified the DB causing us to update the wrong block.
This problem could be fixed by changing keydb_update_keyblock to take a search
description of the keyblock to update. Then it can locate and replace the
record without dropping the lock.
The same basic problem exists for keydb_insert_keyblock. In
import.c:import_one, we check whether the key is in the keyring. If not, then
we insert it using keydb_insert_keyblock. We can fix this by adding a parameter
may_insert to our new keydb_update_keyblock function to indicate whether it is
acceptable to add a new keyblock if one doesn't already exist.