mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-23 15:07:03 +01:00
gpg: Fix trustdb updates without lock held.
* g10/tdbio.c (is_locked): Turn into a counter. (take_write_lock, release_write_lock): Implement recursive locks. -- On trustdb creation we have this call sequence: init_trustdb -> takes lock tdbio_set_dbname create_version_record tdbio_write_record put_record_into_cache -> takes lock put_record_into_cache -> releases lock init_trustdb -> releases lock The second take lock does noting but the first release lock has already released the lock and the second release lock is a thus a NOP. This is likely the cause for the corrupted trustdb as reported in GnuPG-bug-id: 3839 Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
5f00531463
commit
456a3a8e93
39
g10/tdbio.c
39
g10/tdbio.c
@ -105,10 +105,11 @@ struct cmp_xdir_struct
|
|||||||
/* The name of the trustdb file. */
|
/* The name of the trustdb file. */
|
||||||
static char *db_name;
|
static char *db_name;
|
||||||
|
|
||||||
/* The handle for locking the trustdb file and a flag to record
|
/* The handle for locking the trustdb file and a counter to record how
|
||||||
whether a lock has been taken. */
|
* often this lock has been taken. That counter is required becuase
|
||||||
|
* dotlock does not implemen recursive locks. */
|
||||||
static dotlock_t lockhandle;
|
static dotlock_t lockhandle;
|
||||||
static int is_locked;
|
static unsigned int is_locked;
|
||||||
|
|
||||||
/* The file descriptor of the trustdb. */
|
/* The file descriptor of the trustdb. */
|
||||||
static int db_fd = -1;
|
static int db_fd = -1;
|
||||||
@ -135,6 +136,8 @@ static void create_hashtable (ctrl_t ctrl, TRUSTREC *vr, int type);
|
|||||||
static int
|
static int
|
||||||
take_write_lock (void)
|
take_write_lock (void)
|
||||||
{
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (!lockhandle)
|
if (!lockhandle)
|
||||||
lockhandle = dotlock_create (db_name, 0);
|
lockhandle = dotlock_create (db_name, 0);
|
||||||
if (!lockhandle)
|
if (!lockhandle)
|
||||||
@ -144,12 +147,16 @@ take_write_lock (void)
|
|||||||
{
|
{
|
||||||
if (dotlock_take (lockhandle, -1) )
|
if (dotlock_take (lockhandle, -1) )
|
||||||
log_fatal ( _("can't lock '%s'\n"), db_name );
|
log_fatal ( _("can't lock '%s'\n"), db_name );
|
||||||
else
|
rc = 0;
|
||||||
is_locked = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return 1;
|
rc = 1;
|
||||||
|
|
||||||
|
if (opt.lock_once)
|
||||||
|
is_locked = 1;
|
||||||
|
else
|
||||||
|
is_locked++;
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -160,10 +167,22 @@ take_write_lock (void)
|
|||||||
static void
|
static void
|
||||||
release_write_lock (void)
|
release_write_lock (void)
|
||||||
{
|
{
|
||||||
if (!opt.lock_once)
|
if (opt.lock_once)
|
||||||
if (!dotlock_release (lockhandle))
|
return; /* Don't care; here IS_LOCKED is fixed to 1. */
|
||||||
is_locked = 0;
|
|
||||||
|
if (!is_locked)
|
||||||
|
{
|
||||||
|
log_error ("Ooops, tdbio:release_write_lock with no lock held\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (--is_locked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (dotlock_release (lockhandle))
|
||||||
|
log_error ("Oops, tdbio:release_write_locked failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************
|
/*************************************
|
||||||
************* record cache **********
|
************* record cache **********
|
||||||
|
Loading…
x
Reference in New Issue
Block a user