From 39f907cb005fb2f7f68e88cbfa69a2a01ab7da27 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 4 May 2023 12:01:04 +0200 Subject: [PATCH] gpgsm: Try avoiding too many open calls for pubring.kbx. * sm/gpgsm.h (struct server_control_s): Add fields cached_kh and cached_kh_for_set_cert_flags. * sm/certchain.c (do_validate_chain): Cache the keydb handle. * sm/keydb.c (keydb_set_cert_flags): Ditto (keydb_release): Invalidate the caches. -- In particular under Windows opening a file may be a expensive operation if malware^Dantivirus software gets in the way. Due to changed locking behaviour this patch has a regression risk. --- sm/certchain.c | 16 ++++++++++++++-- sm/gpgsm.h | 4 ++++ sm/keydb.c | 35 ++++++++++++++++++++++++----------- 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/sm/certchain.c b/sm/certchain.c index 84dbed696..669a9b385 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -1604,7 +1604,14 @@ do_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime_arg, return 0; } - kh = keydb_new (ctrl); + if (ctrl->cached_kh) + { + kh = ctrl->cached_kh; + ctrl->cached_kh = NULL; + keydb_search_reset (kh); + } + else + kh = keydb_new (ctrl); if (!kh) { log_error (_("failed to allocate keyDB handle\n")); @@ -2147,7 +2154,12 @@ do_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime_arg, gnupg_copy_time (r_exptime, exptime); xfree (issuer); xfree (subject); - keydb_release (kh); + + if (!ctrl->cached_kh) + ctrl->cached_kh = kh; + else + keydb_release (kh); + while (chain) { chain_item_t ci_next = chain->next; diff --git a/sm/gpgsm.h b/sm/gpgsm.h index cef39ff2a..1053f1e9b 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -270,6 +270,10 @@ struct server_control_s /* The revocation info. Used as a helper inc ertchain.c */ gnupg_isotime_t revoked_at; char *revocation_reason; + + /* We cache the key data base handle. */ + void *cached_kh; + void *cached_kh_for_set_cert_flags; }; diff --git a/sm/keydb.c b/sm/keydb.c index 38737c96a..8b5a572da 100644 --- a/sm/keydb.c +++ b/sm/keydb.c @@ -701,6 +701,11 @@ keydb_release (KEYDB_HANDLE hd) } } + if (hd->ctrl->cached_kh == hd) + hd->ctrl->cached_kh = NULL; + if (hd->ctrl->cached_kh_for_set_cert_flags == hd) + hd->ctrl->cached_kh_for_set_cert_flags = NULL; + xfree (hd); if (DBG_CLOCK) log_clock ("%s: leave\n", __func__); @@ -2023,7 +2028,14 @@ keydb_set_cert_flags (ctrl_t ctrl, ksba_cert_t cert, int ephemeral, return gpg_error (GPG_ERR_GENERAL); } - kh = keydb_new (ctrl); + if (ctrl->cached_kh_for_set_cert_flags) + { + kh = ctrl->cached_kh_for_set_cert_flags; + ctrl->cached_kh_for_set_cert_flags = NULL; + keydb_search_reset (kh); + } + else + kh = keydb_new (ctrl); if (!kh) { log_error (_("failed to allocate keyDB handle\n")); @@ -2039,8 +2051,7 @@ keydb_set_cert_flags (ctrl_t ctrl, ksba_cert_t cert, int ephemeral, if (err) { log_error (_("error locking keybox: %s\n"), gpg_strerror (err)); - keydb_release (kh); - return err; + goto leave; } } @@ -2050,16 +2061,14 @@ keydb_set_cert_flags (ctrl_t ctrl, ksba_cert_t cert, int ephemeral, if (gpg_err_code (err) != GPG_ERR_NOT_FOUND) log_error (_("problem re-searching certificate: %s\n"), gpg_strerror (err)); - keydb_release (kh); - return err; + goto leave; } err = keydb_get_flags (kh, which, idx, &old_value); if (err) { log_error (_("error getting stored flags: %s\n"), gpg_strerror (err)); - keydb_release (kh); - return err; + goto leave; } value = ((old_value & ~mask) | (value & mask)); @@ -2070,13 +2079,17 @@ keydb_set_cert_flags (ctrl_t ctrl, ksba_cert_t cert, int ephemeral, if (err) { log_error (_("error storing flags: %s\n"), gpg_strerror (err)); - keydb_release (kh); - return err; + goto leave; } } + err = 0; - keydb_release (kh); - return 0; + leave: + if (!err && !ctrl->cached_kh_for_set_cert_flags) + ctrl->cached_kh_for_set_cert_flags = kh; + else + keydb_release (kh); + return err; }