aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Kahn Gillmor <[email protected]>2016-10-29 05:25:05 +0000
committerNIIBE Yutaka <[email protected]>2018-09-07 05:28:11 +0000
commit04b56eff118ec34432c368b87e724bce1ac683f9 (patch)
tree7233a9522dd168b865592269fe7756e6565f7519
parentg10: Fix memory leak. (diff)
downloadgnupg-04b56eff118ec34432c368b87e724bce1ac683f9.tar.gz
gnupg-04b56eff118ec34432c368b87e724bce1ac683f9.zip
dirmngr: hkp: Avoid potential race condition when some hosts die.
* dirmngr/ks-engine-hkp.c (select_random_host): Use atomic pass through the host table instead of risking out-of-bounds write. -- Multiple threads may write to hosttable[x]->dead while select_random_host() is running. For example, a housekeeping thread might clear the ->dead bit on some entries, or another connection to dirmngr might manually mark a host as alive. If one or more hosts are resurrected between the two loops over a given table in select_random_host(), then the allocation of tbl might not be large enough, resulting in a write past the end of tbl on the second loop. This change collapses the two loops into a single loop to avoid this discrepancy: each host's "dead" bit is now only checked once. As Werner points out, this isn't currently strictly necessary, since npth will not switch threads unless a blocking system call is made, and no blocking system call is made in these two loops. However, in a subsequent change in this series, we will call a function in this loop, and that function may sometimes write(2), or call other functions, which may themselves block. Keeping this as a single-pass loop avoids the need to keep track of what might block and what might not. GnuPG-bug-id: 2836 Signed-off-by: Daniel Kahn Gillmor <[email protected]>
-rw-r--r--dirmngr/ks-engine-hkp.c23
1 files changed, 10 insertions, 13 deletions
diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
index 630309991..49a57ebcf 100644
--- a/dirmngr/ks-engine-hkp.c
+++ b/dirmngr/ks-engine-hkp.c
@@ -221,29 +221,26 @@ host_in_pool_p (hostinfo_t hi, int tblidx)
static int
select_random_host (hostinfo_t hi)
{
- int *tbl;
- size_t tblsize;
+ int *tbl = NULL;
+ size_t tblsize = 0;
int pidx, idx;
/* We create a new table so that we randomly select only from
currently alive hosts. */
- for (idx = 0, tblsize = 0;
+ for (idx = 0;
idx < hi->pool_len && (pidx = hi->pool[idx]) != -1;
idx++)
if (hosttable[pidx] && !hosttable[pidx]->dead)
- tblsize++;
+ {
+ tblsize++;
+ tbl = xtryrealloc(tbl, tblsize * sizeof *tbl);
+ if (!tbl)
+ return -1; /* memory allocation failed! */
+ tbl[tblsize-1] = pidx;
+ }
if (!tblsize)
return -1; /* No hosts. */
- tbl = xtrymalloc (tblsize * sizeof *tbl);
- if (!tbl)
- return -1;
- for (idx = 0, tblsize = 0;
- idx < hi->pool_len && (pidx = hi->pool[idx]) != -1;
- idx++)
- if (hosttable[pidx] && !hosttable[pidx]->dead)
- tbl[tblsize++] = pidx;
-
if (tblsize == 1) /* Save a get_uint_nonce. */
pidx = tbl[0];
else