chiark / gitweb /
Import gnupg2_2.1.17-3.debian.tar.bz2
[gnupg2.git] / patches / dirmngr-idling / 0001-dirmngr-hkp-Avoid-potential-race-condition-when-some.patch
1 From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
2 Date: Sat, 29 Oct 2016 01:25:05 -0400
3 Subject: dirmngr: hkp: Avoid potential race condition when some hosts die.
4
5 * dirmngr/ks-engine-hkp.c (select_random_host): Use atomic pass
6 through the host table instead of risking out-of-bounds write.
7
8 --
9
10 Multiple threads may write to hosttable[x]->dead while
11 select_random_host() is running.  For example, a housekeeping thread
12 might clear the ->dead bit on some entries, or another connection to
13 dirmngr might manually mark a host as alive.
14
15 If one or more hosts are resurrected between the two loops over a
16 given table in select_random_host(), then the allocation of tbl might
17 not be large enough, resulting in a write past the end of tbl on the
18 second loop.
19
20 This change collapses the two loops into a single loop to avoid this
21 discrepancy: each host's "dead" bit is now only checked once.
22
23 As Werner points out, this isn't currently strictly necessary, since
24 npth will not switch threads unless a blocking system call is made,
25 and no blocking system call is made in these two loops.
26
27 However, in a subsequent change in this series, we will call a
28 function in this loop, and that function may sometimes write(2), or
29 call other functions, which may themselves block.  Keeping this as a
30 single-pass loop avoids the need to keep track of what might block and
31 what might not.
32
33 Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
34 ---
35  dirmngr/ks-engine-hkp.c | 21 ++++++++++-----------
36  1 file changed, 10 insertions(+), 11 deletions(-)
37
38 diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c
39 index a6c22f8cd..2d1240bb3 100644
40 --- a/dirmngr/ks-engine-hkp.c
41 +++ b/dirmngr/ks-engine-hkp.c
42 @@ -209,25 +209,24 @@ host_in_pool_p (int *pool, int tblidx)
43  static int
44  select_random_host (int *table)
45  {
46 -  int *tbl;
47 -  size_t tblsize;
48 +  int *tbl = NULL;
49 +  size_t tblsize = 0;
50    int pidx, idx;
51  
52    /* We create a new table so that we randomly select only from
53       currently alive hosts.  */
54 -  for (idx=0, tblsize=0; (pidx = table[idx]) != -1; idx++)
55 +  for (idx=0; (pidx = table[idx]) != -1; idx++)
56      if (hosttable[pidx] && !hosttable[pidx]->dead)
57 -      tblsize++;
58 +      {
59 +        tblsize++;
60 +        tbl = xtryrealloc(tbl, tblsize * sizeof *tbl);
61 +        if (!tbl)
62 +          return -1; /* memory allocation failed! */
63 +        tbl[tblsize-1] = pidx;
64 +      }
65    if (!tblsize)
66      return -1; /* No hosts.  */
67  
68 -  tbl = xtrymalloc (tblsize * sizeof *tbl);
69 -  if (!tbl)
70 -    return -1;
71 -  for (idx=0, tblsize=0; (pidx = table[idx]) != -1; idx++)
72 -    if (hosttable[pidx] && !hosttable[pidx]->dead)
73 -      tbl[tblsize++] = pidx;
74 -
75    if (tblsize == 1)  /* Save a get_uint_nonce.  */
76      pidx = tbl[0];
77    else