diff options
author | Werner Koch <wk@gnupg.org> | 2017-10-18 18:28:52 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2017-10-19 15:02:28 +0200 |
commit | 7c73db3d31c6457dfbdc82a8dc89951c023f0603 (patch) | |
tree | c9a14778d15e4cb06b617fe772f1225c12460183 /g10/keydb.c | |
parent | gpg: Improve keydb handling in the main import function. (diff) | |
download | gnupg2-7c73db3d31c6457dfbdc82a8dc89951c023f0603.tar.xz gnupg2-7c73db3d31c6457dfbdc82a8dc89951c023f0603.zip |
gpg: Keep a lock during the read-update/insert cycle in import.
* g10/keydb.c (keydb_handle): New field 'keep_lock'.
(keydb_release): Clear that flag.
(keydb_lock): New function.
(unlock_all): Skip if KEEP_LOCK is set.
* g10/getkey.c (get_keyblock_byfprint_fast): Call keep_lock if
requested.
--
That change is straightforward. It helps to avoid the race condition
that another gpg process inserts a key while the first process is
between the search and the insert.
A similar change is due for gpgsm.
Note that the key edit operations may still suffer from a race.
GnuPG-bug-id: 3446
Diffstat (limited to 'g10/keydb.c')
-rw-r--r-- | g10/keydb.c | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/g10/keydb.c b/g10/keydb.c index 0f28bc301..58a14a83d 100644 --- a/g10/keydb.c +++ b/g10/keydb.c @@ -96,6 +96,10 @@ struct keydb_handle / keybox_lock, as appropriate). */ int locked; + /* If this flag is set a lock will only be released by + * keydb_release. */ + int keep_lock; + /* The index into ACTIVE of the resources in which the last search result was found. Initially -1. */ int found; @@ -964,6 +968,7 @@ keydb_release (KEYDB_HANDLE hd) log_assert (active_handles > 0); active_handles--; + hd->keep_lock = 0; unlock_all (hd); for (i=0; i < hd->used; i++) { @@ -985,6 +990,24 @@ keydb_release (KEYDB_HANDLE hd) } +/* Take a lock on the files immediately and not only during insert or + * update. This lock is released with keydb_release. */ +gpg_error_t +keydb_lock (KEYDB_HANDLE hd) +{ + gpg_error_t err; + + if (!hd) + return gpg_error (GPG_ERR_INV_ARG); + + err = lock_all (hd); + if (!err) + hd->keep_lock = 1; + + return err; +} + + /* Set a flag on the handle to suppress use of cached results. This * is required for updating a keyring and for key listings. Fixme: * Using a new parameter for keydb_new might be a better solution. */ @@ -1098,7 +1121,7 @@ unlock_all (KEYDB_HANDLE hd) { int i; - if (!hd->locked) + if (!hd->locked || hd->keep_lock) return; for (i=hd->used-1; i >= 0; i--) |