| rev |
line source |
|
shann@25728
|
1 From 4d27d4b9a188786fc6a56745506cec2acfc51f83 Mon Sep 17 00:00:00 2001
|
|
shann@25728
|
2 From: Florian Weimer <fweimer@redhat.com>
|
|
shann@25728
|
3 Date: Thu, 25 Apr 2024 15:01:07 +0200
|
|
shann@25728
|
4 Subject: [PATCH] CVE-2024-33601, CVE-2024-33602: nscd: netgroup: Use two
|
|
shann@25728
|
5 buffers in addgetnetgrentX (bug 31680)
|
|
shann@25728
|
6
|
|
shann@25728
|
7 This avoids potential memory corruption when the underlying NSS
|
|
shann@25728
|
8 callback function does not use the buffer space to store all strings
|
|
shann@25728
|
9 (e.g., for constant strings).
|
|
shann@25728
|
10
|
|
shann@25728
|
11 Instead of custom buffer management, two scratch buffers are used.
|
|
shann@25728
|
12 This increases stack usage somewhat.
|
|
shann@25728
|
13
|
|
shann@25728
|
14 Scratch buffer allocation failure is handled by return -1
|
|
shann@25728
|
15 (an invalid timeout value) instead of terminating the process.
|
|
shann@25728
|
16 This fixes bug 31679.
|
|
shann@25728
|
17
|
|
shann@25728
|
18 Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
|
shann@25728
|
19 (cherry picked from commit c04a21e050d64a1193a6daab872bca2528bda44b)
|
|
shann@25728
|
20 ---
|
|
shann@25728
|
21 nscd/netgroupcache.c | 219 ++++++++++++++++++++++++-------------------
|
|
shann@25728
|
22 1 file changed, 121 insertions(+), 98 deletions(-)
|
|
shann@25728
|
23
|
|
shann@25728
|
24 diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
|
|
shann@25728
|
25 index aa9501a2c05..ee98ffd96ed 100644
|
|
shann@25728
|
26 --- a/nscd/netgroupcache.c
|
|
shann@25728
|
27 +++ b/nscd/netgroupcache.c
|
|
shann@25728
|
28 @@ -24,6 +24,7 @@
|
|
shann@25728
|
29 #include <stdlib.h>
|
|
shann@25728
|
30 #include <unistd.h>
|
|
shann@25728
|
31 #include <sys/mman.h>
|
|
shann@25728
|
32 +#include <scratch_buffer.h>
|
|
shann@25728
|
33
|
|
shann@25728
|
34 #include "../inet/netgroup.h"
|
|
shann@25728
|
35 #include "nscd.h"
|
|
shann@25728
|
36 @@ -66,6 +67,16 @@ struct dataset
|
|
shann@25728
|
37 char strdata[0];
|
|
shann@25728
|
38 };
|
|
shann@25728
|
39
|
|
shann@25728
|
40 +/* Send a notfound response to FD. Always returns -1 to indicate an
|
|
shann@25728
|
41 + ephemeral error. */
|
|
shann@25728
|
42 +static time_t
|
|
shann@25728
|
43 +send_notfound (int fd)
|
|
shann@25728
|
44 +{
|
|
shann@25728
|
45 + if (fd != -1)
|
|
shann@25728
|
46 + TEMP_FAILURE_RETRY (send (fd, ¬found, sizeof (notfound), MSG_NOSIGNAL));
|
|
shann@25728
|
47 + return -1;
|
|
shann@25728
|
48 +}
|
|
shann@25728
|
49 +
|
|
shann@25728
|
50 /* Sends a notfound message and prepares a notfound dataset to write to the
|
|
shann@25728
|
51 cache. Returns true if there was enough memory to allocate the dataset and
|
|
shann@25728
|
52 returns the dataset in DATASETP, total bytes to write in TOTALP and the
|
|
shann@25728
|
53 @@ -84,8 +95,7 @@ do_notfound (struct database_dyn *db, int fd, request_header *req,
|
|
shann@25728
|
54 total = sizeof (notfound);
|
|
shann@25728
|
55 timeout = time (NULL) + db->negtimeout;
|
|
shann@25728
|
56
|
|
shann@25728
|
57 - if (fd != -1)
|
|
shann@25728
|
58 - TEMP_FAILURE_RETRY (send (fd, ¬found, total, MSG_NOSIGNAL));
|
|
shann@25728
|
59 + send_notfound (fd);
|
|
shann@25728
|
60
|
|
shann@25728
|
61 dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1);
|
|
shann@25728
|
62 /* If we cannot permanently store the result, so be it. */
|
|
shann@25728
|
63 @@ -110,11 +120,78 @@ do_notfound (struct database_dyn *db, int fd, request_header *req,
|
|
shann@25728
|
64 return cacheable;
|
|
shann@25728
|
65 }
|
|
shann@25728
|
66
|
|
shann@25728
|
67 +struct addgetnetgrentX_scratch
|
|
shann@25728
|
68 +{
|
|
shann@25728
|
69 + /* This is the result that the caller should use. It can be NULL,
|
|
shann@25728
|
70 + point into buffer, or it can be in the cache. */
|
|
shann@25728
|
71 + struct dataset *dataset;
|
|
shann@25728
|
72 +
|
|
shann@25728
|
73 + struct scratch_buffer buffer;
|
|
shann@25728
|
74 +
|
|
shann@25728
|
75 + /* Used internally in addgetnetgrentX as a staging area. */
|
|
shann@25728
|
76 + struct scratch_buffer tmp;
|
|
shann@25728
|
77 +
|
|
shann@25728
|
78 + /* Number of bytes in buffer that are actually used. */
|
|
shann@25728
|
79 + size_t buffer_used;
|
|
shann@25728
|
80 +};
|
|
shann@25728
|
81 +
|
|
shann@25728
|
82 +static void
|
|
shann@25728
|
83 +addgetnetgrentX_scratch_init (struct addgetnetgrentX_scratch *scratch)
|
|
shann@25728
|
84 +{
|
|
shann@25728
|
85 + scratch->dataset = NULL;
|
|
shann@25728
|
86 + scratch_buffer_init (&scratch->buffer);
|
|
shann@25728
|
87 + scratch_buffer_init (&scratch->tmp);
|
|
shann@25728
|
88 +
|
|
shann@25728
|
89 + /* Reserve space for the header. */
|
|
shann@25728
|
90 + scratch->buffer_used = sizeof (struct dataset);
|
|
shann@25728
|
91 + static_assert (sizeof (struct dataset) < sizeof (scratch->tmp.__space),
|
|
shann@25728
|
92 + "initial buffer space");
|
|
shann@25728
|
93 + memset (scratch->tmp.data, 0, sizeof (struct dataset));
|
|
shann@25728
|
94 +}
|
|
shann@25728
|
95 +
|
|
shann@25728
|
96 +static void
|
|
shann@25728
|
97 +addgetnetgrentX_scratch_free (struct addgetnetgrentX_scratch *scratch)
|
|
shann@25728
|
98 +{
|
|
shann@25728
|
99 + scratch_buffer_free (&scratch->buffer);
|
|
shann@25728
|
100 + scratch_buffer_free (&scratch->tmp);
|
|
shann@25728
|
101 +}
|
|
shann@25728
|
102 +
|
|
shann@25728
|
103 +/* Copy LENGTH bytes from S into SCRATCH. Returns NULL if SCRATCH
|
|
shann@25728
|
104 + could not be resized, otherwise a pointer to the copy. */
|
|
shann@25728
|
105 +static char *
|
|
shann@25728
|
106 +addgetnetgrentX_append_n (struct addgetnetgrentX_scratch *scratch,
|
|
shann@25728
|
107 + const char *s, size_t length)
|
|
shann@25728
|
108 +{
|
|
shann@25728
|
109 + while (true)
|
|
shann@25728
|
110 + {
|
|
shann@25728
|
111 + size_t remaining = scratch->buffer.length - scratch->buffer_used;
|
|
shann@25728
|
112 + if (remaining >= length)
|
|
shann@25728
|
113 + break;
|
|
shann@25728
|
114 + if (!scratch_buffer_grow_preserve (&scratch->buffer))
|
|
shann@25728
|
115 + return NULL;
|
|
shann@25728
|
116 + }
|
|
shann@25728
|
117 + char *copy = scratch->buffer.data + scratch->buffer_used;
|
|
shann@25728
|
118 + memcpy (copy, s, length);
|
|
shann@25728
|
119 + scratch->buffer_used += length;
|
|
shann@25728
|
120 + return copy;
|
|
shann@25728
|
121 +}
|
|
shann@25728
|
122 +
|
|
shann@25728
|
123 +/* Copy S into SCRATCH, including its null terminator. Returns false
|
|
shann@25728
|
124 + if SCRATCH could not be resized. */
|
|
shann@25728
|
125 +static bool
|
|
shann@25728
|
126 +addgetnetgrentX_append (struct addgetnetgrentX_scratch *scratch, const char *s)
|
|
shann@25728
|
127 +{
|
|
shann@25728
|
128 + if (s == NULL)
|
|
shann@25728
|
129 + s = "";
|
|
shann@25728
|
130 + return addgetnetgrentX_append_n (scratch, s, strlen (s) + 1) != NULL;
|
|
shann@25728
|
131 +}
|
|
shann@25728
|
132 +
|
|
shann@25728
|
133 +/* Caller must initialize and free *SCRATCH. If the return value is
|
|
shann@25728
|
134 + negative, this function has sent a notfound response. */
|
|
shann@25728
|
135 static time_t
|
|
shann@25728
|
136 addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
|
shann@25728
|
137 const char *key, uid_t uid, struct hashentry *he,
|
|
shann@25728
|
138 - struct datahead *dh, struct dataset **resultp,
|
|
shann@25728
|
139 - void **tofreep)
|
|
shann@25728
|
140 + struct datahead *dh, struct addgetnetgrentX_scratch *scratch)
|
|
shann@25728
|
141 {
|
|
shann@25728
|
142 if (__glibc_unlikely (debug_level > 0))
|
|
shann@25728
|
143 {
|
|
shann@25728
|
144 @@ -133,14 +210,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
|
shann@25728
|
145
|
|
shann@25728
|
146 char *key_copy = NULL;
|
|
shann@25728
|
147 struct __netgrent data;
|
|
shann@25728
|
148 - size_t buflen = MAX (1024, sizeof (*dataset) + req->key_len);
|
|
shann@25728
|
149 - size_t buffilled = sizeof (*dataset);
|
|
shann@25728
|
150 - char *buffer = NULL;
|
|
shann@25728
|
151 size_t nentries = 0;
|
|
shann@25728
|
152 size_t group_len = strlen (key) + 1;
|
|
shann@25728
|
153 struct name_list *first_needed
|
|
shann@25728
|
154 = alloca (sizeof (struct name_list) + group_len);
|
|
shann@25728
|
155 - *tofreep = NULL;
|
|
shann@25728
|
156
|
|
shann@25728
|
157 if (netgroup_database == NULL
|
|
shann@25728
|
158 && __nss_database_lookup2 ("netgroup", NULL, NULL, &netgroup_database))
|
|
shann@25728
|
159 @@ -152,8 +225,6 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
|
shann@25728
|
160 }
|
|
shann@25728
|
161
|
|
shann@25728
|
162 memset (&data, '\0', sizeof (data));
|
|
shann@25728
|
163 - buffer = xmalloc (buflen);
|
|
shann@25728
|
164 - *tofreep = buffer;
|
|
shann@25728
|
165 first_needed->next = first_needed;
|
|
shann@25728
|
166 memcpy (first_needed->name, key, group_len);
|
|
shann@25728
|
167 data.needed_groups = first_needed;
|
|
shann@25728
|
168 @@ -196,8 +267,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
|
shann@25728
|
169 while (1)
|
|
shann@25728
|
170 {
|
|
shann@25728
|
171 int e;
|
|
shann@25728
|
172 - status = getfct.f (&data, buffer + buffilled,
|
|
shann@25728
|
173 - buflen - buffilled - req->key_len, &e);
|
|
shann@25728
|
174 + status = getfct.f (&data, scratch->tmp.data,
|
|
shann@25728
|
175 + scratch->tmp.length, &e);
|
|
shann@25728
|
176 if (status == NSS_STATUS_SUCCESS)
|
|
shann@25728
|
177 {
|
|
shann@25728
|
178 if (data.type == triple_val)
|
|
shann@25728
|
179 @@ -205,68 +276,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
|
shann@25728
|
180 const char *nhost = data.val.triple.host;
|
|
shann@25728
|
181 const char *nuser = data.val.triple.user;
|
|
shann@25728
|
182 const char *ndomain = data.val.triple.domain;
|
|
shann@25728
|
183 -
|
|
shann@25728
|
184 - size_t hostlen = strlen (nhost ?: "") + 1;
|
|
shann@25728
|
185 - size_t userlen = strlen (nuser ?: "") + 1;
|
|
shann@25728
|
186 - size_t domainlen = strlen (ndomain ?: "") + 1;
|
|
shann@25728
|
187 -
|
|
shann@25728
|
188 - if (nhost == NULL || nuser == NULL || ndomain == NULL
|
|
shann@25728
|
189 - || nhost > nuser || nuser > ndomain)
|
|
shann@25728
|
190 - {
|
|
shann@25728
|
191 - const char *last = nhost;
|
|
shann@25728
|
192 - if (last == NULL
|
|
shann@25728
|
193 - || (nuser != NULL && nuser > last))
|
|
shann@25728
|
194 - last = nuser;
|
|
shann@25728
|
195 - if (last == NULL
|
|
shann@25728
|
196 - || (ndomain != NULL && ndomain > last))
|
|
shann@25728
|
197 - last = ndomain;
|
|
shann@25728
|
198 -
|
|
shann@25728
|
199 - size_t bufused
|
|
shann@25728
|
200 - = (last == NULL
|
|
shann@25728
|
201 - ? buffilled
|
|
shann@25728
|
202 - : last + strlen (last) + 1 - buffer);
|
|
shann@25728
|
203 -
|
|
shann@25728
|
204 - /* We have to make temporary copies. */
|
|
shann@25728
|
205 - size_t needed = hostlen + userlen + domainlen;
|
|
shann@25728
|
206 -
|
|
shann@25728
|
207 - if (buflen - req->key_len - bufused < needed)
|
|
shann@25728
|
208 - {
|
|
shann@25728
|
209 - buflen += MAX (buflen, 2 * needed);
|
|
shann@25728
|
210 - /* Save offset in the old buffer. We don't
|
|
shann@25728
|
211 - bother with the NULL check here since
|
|
shann@25728
|
212 - we'll do that later anyway. */
|
|
shann@25728
|
213 - size_t nhostdiff = nhost - buffer;
|
|
shann@25728
|
214 - size_t nuserdiff = nuser - buffer;
|
|
shann@25728
|
215 - size_t ndomaindiff = ndomain - buffer;
|
|
shann@25728
|
216 -
|
|
shann@25728
|
217 - char *newbuf = xrealloc (buffer, buflen);
|
|
shann@25728
|
218 - /* Fix up the triplet pointers into the new
|
|
shann@25728
|
219 - buffer. */
|
|
shann@25728
|
220 - nhost = (nhost ? newbuf + nhostdiff
|
|
shann@25728
|
221 - : NULL);
|
|
shann@25728
|
222 - nuser = (nuser ? newbuf + nuserdiff
|
|
shann@25728
|
223 - : NULL);
|
|
shann@25728
|
224 - ndomain = (ndomain ? newbuf + ndomaindiff
|
|
shann@25728
|
225 - : NULL);
|
|
shann@25728
|
226 - *tofreep = buffer = newbuf;
|
|
shann@25728
|
227 - }
|
|
shann@25728
|
228 -
|
|
shann@25728
|
229 - nhost = memcpy (buffer + bufused,
|
|
shann@25728
|
230 - nhost ?: "", hostlen);
|
|
shann@25728
|
231 - nuser = memcpy ((char *) nhost + hostlen,
|
|
shann@25728
|
232 - nuser ?: "", userlen);
|
|
shann@25728
|
233 - ndomain = memcpy ((char *) nuser + userlen,
|
|
shann@25728
|
234 - ndomain ?: "", domainlen);
|
|
shann@25728
|
235 - }
|
|
shann@25728
|
236 -
|
|
shann@25728
|
237 - char *wp = buffer + buffilled;
|
|
shann@25728
|
238 - wp = memmove (wp, nhost ?: "", hostlen);
|
|
shann@25728
|
239 - wp += hostlen;
|
|
shann@25728
|
240 - wp = memmove (wp, nuser ?: "", userlen);
|
|
shann@25728
|
241 - wp += userlen;
|
|
shann@25728
|
242 - wp = memmove (wp, ndomain ?: "", domainlen);
|
|
shann@25728
|
243 - wp += domainlen;
|
|
shann@25728
|
244 - buffilled = wp - buffer;
|
|
shann@25728
|
245 + if (!(addgetnetgrentX_append (scratch, nhost)
|
|
shann@25728
|
246 + && addgetnetgrentX_append (scratch, nuser)
|
|
shann@25728
|
247 + && addgetnetgrentX_append (scratch, ndomain)))
|
|
shann@25728
|
248 + return send_notfound (fd);
|
|
shann@25728
|
249 ++nentries;
|
|
shann@25728
|
250 }
|
|
shann@25728
|
251 else
|
|
shann@25728
|
252 @@ -318,8 +331,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
|
shann@25728
|
253 }
|
|
shann@25728
|
254 else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE)
|
|
shann@25728
|
255 {
|
|
shann@25728
|
256 - buflen *= 2;
|
|
shann@25728
|
257 - *tofreep = buffer = xrealloc (buffer, buflen);
|
|
shann@25728
|
258 + if (!scratch_buffer_grow (&scratch->tmp))
|
|
shann@25728
|
259 + return send_notfound (fd);
|
|
shann@25728
|
260 }
|
|
shann@25728
|
261 else if (status == NSS_STATUS_RETURN
|
|
shann@25728
|
262 || status == NSS_STATUS_NOTFOUND
|
|
shann@25728
|
263 @@ -352,10 +365,17 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
|
shann@25728
|
264 goto maybe_cache_add;
|
|
shann@25728
|
265 }
|
|
shann@25728
|
266
|
|
shann@25728
|
267 - total = buffilled;
|
|
shann@25728
|
268 + /* Capture the result size without the key appended. */
|
|
shann@25728
|
269 + total = scratch->buffer_used;
|
|
shann@25728
|
270 +
|
|
shann@25728
|
271 + /* Make a copy of the key. The scratch buffer must not move after
|
|
shann@25728
|
272 + this point. */
|
|
shann@25728
|
273 + key_copy = addgetnetgrentX_append_n (scratch, key, req->key_len);
|
|
shann@25728
|
274 + if (key_copy == NULL)
|
|
shann@25728
|
275 + return send_notfound (fd);
|
|
shann@25728
|
276
|
|
shann@25728
|
277 /* Fill in the dataset. */
|
|
shann@25728
|
278 - dataset = (struct dataset *) buffer;
|
|
shann@25728
|
279 + dataset = scratch->buffer.data;
|
|
shann@25728
|
280 timeout = datahead_init_pos (&dataset->head, total + req->key_len,
|
|
shann@25728
|
281 total - offsetof (struct dataset, resp),
|
|
shann@25728
|
282 he == NULL ? 0 : dh->nreloads + 1,
|
|
shann@25728
|
283 @@ -364,11 +384,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
|
shann@25728
|
284 dataset->resp.version = NSCD_VERSION;
|
|
shann@25728
|
285 dataset->resp.found = 1;
|
|
shann@25728
|
286 dataset->resp.nresults = nentries;
|
|
shann@25728
|
287 - dataset->resp.result_len = buffilled - sizeof (*dataset);
|
|
shann@25728
|
288 -
|
|
shann@25728
|
289 - assert (buflen - buffilled >= req->key_len);
|
|
shann@25728
|
290 - key_copy = memcpy (buffer + buffilled, key, req->key_len);
|
|
shann@25728
|
291 - buffilled += req->key_len;
|
|
shann@25728
|
292 + dataset->resp.result_len = total - sizeof (*dataset);
|
|
shann@25728
|
293
|
|
shann@25728
|
294 /* Now we can determine whether on refill we have to create a new
|
|
shann@25728
|
295 record or not. */
|
|
shann@25728
|
296 @@ -399,7 +415,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
|
shann@25728
|
297 if (__glibc_likely (newp != NULL))
|
|
shann@25728
|
298 {
|
|
shann@25728
|
299 /* Adjust pointer into the memory block. */
|
|
shann@25728
|
300 - key_copy = (char *) newp + (key_copy - buffer);
|
|
shann@25728
|
301 + key_copy = (char *) newp + (key_copy - (char *) dataset);
|
|
shann@25728
|
302
|
|
shann@25728
|
303 dataset = memcpy (newp, dataset, total + req->key_len);
|
|
shann@25728
|
304 cacheable = true;
|
|
shann@25728
|
305 @@ -440,7 +456,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
|
shann@25728
|
306 }
|
|
shann@25728
|
307
|
|
shann@25728
|
308 out:
|
|
shann@25728
|
309 - *resultp = dataset;
|
|
shann@25728
|
310 + scratch->dataset = dataset;
|
|
shann@25728
|
311
|
|
shann@25728
|
312 return timeout;
|
|
shann@25728
|
313 }
|
|
shann@25728
|
314 @@ -461,6 +477,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
|
shann@25728
|
315 if (user != NULL)
|
|
shann@25728
|
316 key = (char *) rawmemchr (key, '\0') + 1;
|
|
shann@25728
|
317 const char *domain = *key++ ? key : NULL;
|
|
shann@25728
|
318 + struct addgetnetgrentX_scratch scratch;
|
|
shann@25728
|
319 +
|
|
shann@25728
|
320 + addgetnetgrentX_scratch_init (&scratch);
|
|
shann@25728
|
321
|
|
shann@25728
|
322 if (__glibc_unlikely (debug_level > 0))
|
|
shann@25728
|
323 {
|
|
shann@25728
|
324 @@ -476,12 +495,8 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
|
shann@25728
|
325 group, group_len,
|
|
shann@25728
|
326 db, uid);
|
|
shann@25728
|
327 time_t timeout;
|
|
shann@25728
|
328 - void *tofree;
|
|
shann@25728
|
329 if (result != NULL)
|
|
shann@25728
|
330 - {
|
|
shann@25728
|
331 - timeout = result->head.timeout;
|
|
shann@25728
|
332 - tofree = NULL;
|
|
shann@25728
|
333 - }
|
|
shann@25728
|
334 + timeout = result->head.timeout;
|
|
shann@25728
|
335 else
|
|
shann@25728
|
336 {
|
|
shann@25728
|
337 request_header req_get =
|
|
shann@25728
|
338 @@ -490,7 +505,10 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
|
shann@25728
|
339 .key_len = group_len
|
|
shann@25728
|
340 };
|
|
shann@25728
|
341 timeout = addgetnetgrentX (db, -1, &req_get, group, uid, NULL, NULL,
|
|
shann@25728
|
342 - &result, &tofree);
|
|
shann@25728
|
343 + &scratch);
|
|
shann@25728
|
344 + result = scratch.dataset;
|
|
shann@25728
|
345 + if (timeout < 0)
|
|
shann@25728
|
346 + goto out;
|
|
shann@25728
|
347 }
|
|
shann@25728
|
348
|
|
shann@25728
|
349 struct indataset
|
|
shann@25728
|
350 @@ -604,7 +622,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
|
shann@25728
|
351 }
|
|
shann@25728
|
352
|
|
shann@25728
|
353 out:
|
|
shann@25728
|
354 - free (tofree);
|
|
shann@25728
|
355 + addgetnetgrentX_scratch_free (&scratch);
|
|
shann@25728
|
356 return timeout;
|
|
shann@25728
|
357 }
|
|
shann@25728
|
358
|
|
shann@25728
|
359 @@ -614,11 +632,12 @@ addgetnetgrentX_ignore (struct database_dyn *db, int fd, request_header *req,
|
|
shann@25728
|
360 const char *key, uid_t uid, struct hashentry *he,
|
|
shann@25728
|
361 struct datahead *dh)
|
|
shann@25728
|
362 {
|
|
shann@25728
|
363 - struct dataset *ignore;
|
|
shann@25728
|
364 - void *tofree;
|
|
shann@25728
|
365 - time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh,
|
|
shann@25728
|
366 - &ignore, &tofree);
|
|
shann@25728
|
367 - free (tofree);
|
|
shann@25728
|
368 + struct addgetnetgrentX_scratch scratch;
|
|
shann@25728
|
369 + addgetnetgrentX_scratch_init (&scratch);
|
|
shann@25728
|
370 + time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh, &scratch);
|
|
shann@25728
|
371 + addgetnetgrentX_scratch_free (&scratch);
|
|
shann@25728
|
372 + if (timeout < 0)
|
|
shann@25728
|
373 + timeout = 0;
|
|
shann@25728
|
374 return timeout;
|
|
shann@25728
|
375 }
|
|
shann@25728
|
376
|
|
shann@25728
|
377 @@ -662,5 +681,9 @@ readdinnetgr (struct database_dyn *db, struct hashentry *he,
|
|
shann@25728
|
378 .key_len = he->len
|
|
shann@25728
|
379 };
|
|
shann@25728
|
380
|
|
shann@25728
|
381 - return addinnetgrX (db, -1, &req, db->data + he->key, he->owner, he, dh);
|
|
shann@25728
|
382 + int timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner,
|
|
shann@25728
|
383 + he, dh);
|
|
shann@25728
|
384 + if (timeout < 0)
|
|
shann@25728
|
385 + timeout = 0;
|
|
shann@25728
|
386 + return timeout;
|
|
shann@25728
|
387 }
|