1 /* Cache handling for host lookup.
2    Copyright (C) 1998-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published
7    by the Free Software Foundation; version 2 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, see <https://www.gnu.org/licenses/>.  */
17 
18 #include <alloca.h>
19 #include <assert.h>
20 #include <errno.h>
21 #include <error.h>
22 #include <libintl.h>
23 #include <netdb.h>
24 #include <stdbool.h>
25 #include <stddef.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <time.h>
30 #include <unistd.h>
31 #include <stdint.h>
32 #include <arpa/inet.h>
33 #include <arpa/nameser.h>
34 #include <sys/mman.h>
35 #include <stackinfo.h>
36 #include <scratch_buffer.h>
37 
38 #include "nscd.h"
39 #include "dbg_log.h"
40 
41 
42 /* This is the standard reply in case the service is disabled.  */
43 static const hst_response_header disabled =
44 {
45   .version = NSCD_VERSION,
46   .found = -1,
47   .h_name_len = 0,
48   .h_aliases_cnt = 0,
49   .h_addrtype = -1,
50   .h_length = -1,
51   .h_addr_list_cnt = 0,
52   .error = NETDB_INTERNAL
53 };
54 
55 /* This is the struct describing how to write this record.  */
56 const struct iovec hst_iov_disabled =
57 {
58   .iov_base = (void *) &disabled,
59   .iov_len = sizeof (disabled)
60 };
61 
62 
63 /* This is the standard reply in case we haven't found the dataset.  */
64 static const hst_response_header notfound =
65 {
66   .version = NSCD_VERSION,
67   .found = 0,
68   .h_name_len = 0,
69   .h_aliases_cnt = 0,
70   .h_addrtype = -1,
71   .h_length = -1,
72   .h_addr_list_cnt = 0,
73   .error = HOST_NOT_FOUND
74 };
75 
76 
77 /* This is the standard reply in case there are temporary problems.  */
78 static const hst_response_header tryagain =
79 {
80   .version = NSCD_VERSION,
81   .found = 0,
82   .h_name_len = 0,
83   .h_aliases_cnt = 0,
84   .h_addrtype = -1,
85   .h_length = -1,
86   .h_addr_list_cnt = 0,
87   .error = TRY_AGAIN
88 };
89 
90 
91 static time_t
cache_addhst(struct database_dyn * db,int fd,request_header * req,const void * key,struct hostent * hst,uid_t owner,struct hashentry * const he,struct datahead * dh,int errval,int32_t ttl)92 cache_addhst (struct database_dyn *db, int fd, request_header *req,
93 	      const void *key, struct hostent *hst, uid_t owner,
94 	      struct hashentry *const he, struct datahead *dh, int errval,
95 	      int32_t ttl)
96 {
97   bool all_written = true;
98   time_t t = time (NULL);
99 
100   /* We allocate all data in one memory block: the iov vector,
101      the response header and the dataset itself.  */
102   struct dataset
103   {
104     struct datahead head;
105     hst_response_header resp;
106     char strdata[0];
107   } *dataset;
108 
109   assert (offsetof (struct dataset, resp) == offsetof (struct datahead, data));
110 
111   time_t timeout = MAX_TIMEOUT_VALUE;
112   if (hst == NULL)
113     {
114       if (he != NULL && errval == EAGAIN)
115 	{
116 	  /* If we have an old record available but cannot find one
117 	     now because the service is not available we keep the old
118 	     record and make sure it does not get removed.  */
119 	  if (reload_count != UINT_MAX)
120 	    /* Do not reset the value if we never not reload the record.  */
121 	    dh->nreloads = reload_count - 1;
122 
123 	  /* Reload with the same time-to-live value.  */
124 	  timeout = dh->timeout = t + dh->ttl;
125 	}
126       else
127 	{
128 	  /* We have no data.  This means we send the standard reply for this
129 	     case.  Possibly this is only temporary.  */
130 	  ssize_t total = sizeof (notfound);
131 	  assert (sizeof (notfound) == sizeof (tryagain));
132 
133 	  const hst_response_header *resp = (errval == EAGAIN
134 					     ? &tryagain : &notfound);
135 
136 	  if (fd != -1
137 	      && TEMP_FAILURE_RETRY (send (fd, resp, total,
138 					   MSG_NOSIGNAL)) != total)
139 	    all_written = false;
140 
141 	  /* If we have a transient error or cannot permanently store
142 	     the result, so be it.  */
143 	  if (errval == EAGAIN || __builtin_expect (db->negtimeout == 0, 0))
144 	    {
145 	      /* Mark the old entry as obsolete.  */
146 	      if (dh != NULL)
147 		dh->usable = false;
148 	    }
149 	  else if ((dataset = mempool_alloc (db, (sizeof (struct dataset)
150 						  + req->key_len), 1)) != NULL)
151 	    {
152 	      timeout = datahead_init_neg (&dataset->head,
153 					   (sizeof (struct dataset)
154 					    + req->key_len), total,
155 					   (ttl == INT32_MAX
156 					    ? db->negtimeout : ttl));
157 
158 	      /* This is the reply.  */
159 	      memcpy (&dataset->resp, resp, total);
160 
161 	      /* Copy the key data.  */
162 	      memcpy (dataset->strdata, key, req->key_len);
163 
164 	      /* If necessary, we also propagate the data to disk.  */
165 	      if (db->persistent)
166 		{
167 		  // XXX async OK?
168 		  uintptr_t pval = (uintptr_t) dataset & ~pagesize_m1;
169 		  msync ((void *) pval,
170 			 ((uintptr_t) dataset & pagesize_m1)
171 			 + sizeof (struct dataset) + req->key_len, MS_ASYNC);
172 		}
173 
174 	      (void) cache_add (req->type, &dataset->strdata, req->key_len,
175 				&dataset->head, true, db, owner, he == NULL);
176 
177 	      pthread_rwlock_unlock (&db->lock);
178 
179 	      /* Mark the old entry as obsolete.  */
180 	      if (dh != NULL)
181 		dh->usable = false;
182 	    }
183 	}
184     }
185   else
186     {
187       /* Determine the I/O structure.  */
188       size_t h_name_len = strlen (hst->h_name) + 1;
189       size_t h_aliases_cnt;
190       uint32_t *h_aliases_len;
191       size_t h_addr_list_cnt;
192       char *addresses;
193       char *aliases;
194       char *key_copy = NULL;
195       char *cp;
196       size_t cnt;
197       ssize_t total;
198 
199       /* Determine the number of aliases.  */
200       h_aliases_cnt = 0;
201       for (cnt = 0; hst->h_aliases[cnt] != NULL; ++cnt)
202 	++h_aliases_cnt;
203       /* Determine the length of all aliases.  */
204       h_aliases_len = (uint32_t *) alloca (h_aliases_cnt * sizeof (uint32_t));
205       total = 0;
206       for (cnt = 0; cnt < h_aliases_cnt; ++cnt)
207 	{
208 	  h_aliases_len[cnt] = strlen (hst->h_aliases[cnt]) + 1;
209 	  total += h_aliases_len[cnt];
210 	}
211 
212       /* Determine the number of addresses.  */
213       h_addr_list_cnt = 0;
214       while (hst->h_addr_list[h_addr_list_cnt] != NULL)
215 	++h_addr_list_cnt;
216 
217       if (h_addr_list_cnt == 0)
218 	/* Invalid entry.  */
219 	return MAX_TIMEOUT_VALUE;
220 
221       total += (sizeof (struct dataset)
222 		+ h_name_len
223 		+ h_aliases_cnt * sizeof (uint32_t)
224 		+ h_addr_list_cnt * hst->h_length);
225 
226       /* If we refill the cache, first assume the reconrd did not
227 	 change.  Allocate memory on the cache since it is likely
228 	 discarded anyway.  If it turns out to be necessary to have a
229 	 new record we can still allocate real memory.  */
230       bool alloca_used = false;
231       dataset = NULL;
232 
233       /* If the record contains more than one IP address (used for
234 	 load balancing etc) don't cache the entry.  This is something
235 	 the current cache handling cannot handle and it is more than
236 	 questionable whether it is worthwhile complicating the cache
237 	 handling just for handling such a special case. */
238       if (he == NULL && h_addr_list_cnt == 1)
239 	dataset = (struct dataset *) mempool_alloc (db, total + req->key_len,
240 						    1);
241 
242       if (dataset == NULL)
243 	{
244 	  /* We cannot permanently add the result in the moment.  But
245 	     we can provide the result as is.  Store the data in some
246 	     temporary memory.  */
247 	  dataset = (struct dataset *) alloca (total + req->key_len);
248 
249 	  /* We cannot add this record to the permanent database.  */
250 	  alloca_used = true;
251 	}
252 
253       timeout = datahead_init_pos (&dataset->head, total + req->key_len,
254 				   total - offsetof (struct dataset, resp),
255 				   he == NULL ? 0 : dh->nreloads + 1,
256 				   ttl == INT32_MAX ? db->postimeout : ttl);
257 
258       dataset->resp.version = NSCD_VERSION;
259       dataset->resp.found = 1;
260       dataset->resp.h_name_len = h_name_len;
261       dataset->resp.h_aliases_cnt = h_aliases_cnt;
262       dataset->resp.h_addrtype = hst->h_addrtype;
263       dataset->resp.h_length = hst->h_length;
264       dataset->resp.h_addr_list_cnt = h_addr_list_cnt;
265       dataset->resp.error = NETDB_SUCCESS;
266 
267       /* Make sure there is no gap.  */
268       assert ((char *) (&dataset->resp.error + 1) == dataset->strdata);
269 
270       cp = dataset->strdata;
271 
272       cp = mempcpy (cp, hst->h_name, h_name_len);
273       cp = mempcpy (cp, h_aliases_len, h_aliases_cnt * sizeof (uint32_t));
274 
275       /* The normal addresses first.  */
276       addresses = cp;
277       for (cnt = 0; cnt < h_addr_list_cnt; ++cnt)
278 	cp = mempcpy (cp, hst->h_addr_list[cnt], hst->h_length);
279 
280       /* Then the aliases.  */
281       aliases = cp;
282       for (cnt = 0; cnt < h_aliases_cnt; ++cnt)
283 	cp = mempcpy (cp, hst->h_aliases[cnt], h_aliases_len[cnt]);
284 
285       assert (cp
286 	      == dataset->strdata + total - offsetof (struct dataset,
287 						      strdata));
288 
289       /* If we are adding a GETHOSTBYNAME{,v6} entry we must be prepared
290 	 that the answer we get from the NSS does not contain the key
291 	 itself.  This is the case if the resolver is used and the name
292 	 is extended by the domainnames from /etc/resolv.conf.  Therefore
293 	 we explicitly add the name here.  */
294       key_copy = memcpy (cp, key, req->key_len);
295 
296       assert ((char *) &dataset->resp + dataset->head.recsize == cp);
297 
298       /* Now we can determine whether on refill we have to create a new
299 	 record or not.  */
300       if (he != NULL)
301 	{
302 	  assert (fd == -1);
303 
304 	  if (total + req->key_len == dh->allocsize
305 	      && total - offsetof (struct dataset, resp) == dh->recsize
306 	      && memcmp (&dataset->resp, dh->data,
307 			 dh->allocsize - offsetof (struct dataset, resp)) == 0)
308 	    {
309 	      /* The data has not changed.  We will just bump the
310 		 timeout value.  Note that the new record has been
311 		 allocated on the stack and need not be freed.  */
312 	      assert (h_addr_list_cnt == 1);
313 	      dh->ttl = dataset->head.ttl;
314 	      dh->timeout = dataset->head.timeout;
315 	      ++dh->nreloads;
316 	    }
317 	  else
318 	    {
319 	      if (h_addr_list_cnt == 1)
320 		{
321 		  /* We have to create a new record.  Just allocate
322 		     appropriate memory and copy it.  */
323 		  struct dataset *newp
324 		    = (struct dataset *) mempool_alloc (db,
325 							total + req->key_len,
326 							1);
327 		  if (newp != NULL)
328 		    {
329 		      /* Adjust pointers into the memory block.  */
330 		      addresses = (char *) newp + (addresses
331 						   - (char *) dataset);
332 		      aliases = (char *) newp + (aliases - (char *) dataset);
333 		      assert (key_copy != NULL);
334 		      key_copy = (char *) newp + (key_copy - (char *) dataset);
335 
336 		      dataset = memcpy (newp, dataset, total + req->key_len);
337 		      alloca_used = false;
338 		    }
339 		}
340 
341 	      /* Mark the old record as obsolete.  */
342 	      dh->usable = false;
343 	    }
344 	}
345       else
346 	{
347 	  /* We write the dataset before inserting it to the database
348 	     since while inserting this thread might block and so would
349 	     unnecessarily keep the receiver waiting.  */
350 	  assert (fd != -1);
351 
352 	  if (writeall (fd, &dataset->resp, dataset->head.recsize)
353 	      != dataset->head.recsize)
354 	    all_written = false;
355 	}
356 
357       /* Add the record to the database.  But only if it has not been
358 	 stored on the stack.
359 
360 	 If the record contains more than one IP address (used for
361 	 load balancing etc) don't cache the entry.  This is something
362 	 the current cache handling cannot handle and it is more than
363 	 questionable whether it is worthwhile complicating the cache
364 	 handling just for handling such a special case. */
365       if (! alloca_used)
366 	{
367 	  /* If necessary, we also propagate the data to disk.  */
368 	  if (db->persistent)
369 	    {
370 	      // XXX async OK?
371 	      uintptr_t pval = (uintptr_t) dataset & ~pagesize_m1;
372 	      msync ((void *) pval,
373 		     ((uintptr_t) dataset & pagesize_m1)
374 		     + total + req->key_len, MS_ASYNC);
375 	    }
376 
377 	  /* NB: the following code is really complicated.  It has
378 	     seemlingly duplicated code paths which do the same.  The
379 	     problem is that we always must add the hash table entry
380 	     with the FIRST flag set first.  Otherwise we get dangling
381 	     pointers in case memory allocation fails.  */
382 	  assert (hst->h_addr_list[1] == NULL);
383 
384 	  /* Avoid adding names if more than one address is available.  See
385 	     above for more info.  */
386 	  assert (req->type == GETHOSTBYNAME
387 		  || req->type == GETHOSTBYNAMEv6
388 		  || req->type == GETHOSTBYADDR
389 		  || req->type == GETHOSTBYADDRv6);
390 
391 	  (void) cache_add (req->type, key_copy, req->key_len,
392 			    &dataset->head, true, db, owner, he == NULL);
393 
394 	  pthread_rwlock_unlock (&db->lock);
395 	}
396     }
397 
398   if (__builtin_expect (!all_written, 0) && debug_level > 0)
399     {
400       char buf[256];
401       dbg_log (_("short write in %s: %s"),  __FUNCTION__,
402 	       strerror_r (errno, buf, sizeof (buf)));
403     }
404 
405   return timeout;
406 }
407 
408 
409 static int
lookup(int type,void * key,struct hostent * resultbufp,char * buffer,size_t buflen,struct hostent ** hst,int32_t * ttlp)410 lookup (int type, void *key, struct hostent *resultbufp, char *buffer,
411 	size_t buflen, struct hostent **hst, int32_t *ttlp)
412 {
413   if (type == GETHOSTBYNAME)
414     return __gethostbyname3_r (key, AF_INET, resultbufp, buffer, buflen, hst,
415 			       &h_errno, ttlp, NULL);
416   if (type == GETHOSTBYNAMEv6)
417     return __gethostbyname3_r (key, AF_INET6, resultbufp, buffer, buflen, hst,
418 			       &h_errno, ttlp, NULL);
419   if (type == GETHOSTBYADDR)
420     return __gethostbyaddr2_r (key, NS_INADDRSZ, AF_INET, resultbufp, buffer,
421 			       buflen, hst, &h_errno, ttlp);
422   return __gethostbyaddr2_r (key, NS_IN6ADDRSZ, AF_INET6, resultbufp, buffer,
423 			     buflen, hst, &h_errno, ttlp);
424 }
425 
426 
427 static time_t
addhstbyX(struct database_dyn * db,int fd,request_header * req,void * key,uid_t uid,struct hashentry * he,struct datahead * dh)428 addhstbyX (struct database_dyn *db, int fd, request_header *req,
429 	   void *key, uid_t uid, struct hashentry *he, struct datahead *dh)
430 {
431   /* Search for the entry matching the key.  Please note that we don't
432      look again in the table whether the dataset is now available.  We
433      simply insert it.  It does not matter if it is in there twice.  The
434      pruning function only will look at the timestamp.  */
435   struct hostent resultbuf;
436   struct hostent *hst;
437   int errval = 0;
438   int32_t ttl = INT32_MAX;
439 
440   if (__glibc_unlikely (debug_level > 0))
441     {
442       const char *str;
443       char buf[INET6_ADDRSTRLEN + 1];
444       if (req->type == GETHOSTBYNAME || req->type == GETHOSTBYNAMEv6)
445 	str = key;
446       else
447 	str = inet_ntop (req->type == GETHOSTBYADDR ? AF_INET : AF_INET6,
448 			 key, buf, sizeof (buf));
449 
450       if (he == NULL)
451 	dbg_log (_("Haven't found \"%s\" in hosts cache!"), (char *) str);
452       else
453 	dbg_log (_("Reloading \"%s\" in hosts cache!"), (char *) str);
454     }
455 
456   struct scratch_buffer tmpbuf;
457   scratch_buffer_init (&tmpbuf);
458 
459   while (lookup (req->type, key, &resultbuf,
460 		 tmpbuf.data, tmpbuf.length, &hst, &ttl) != 0
461 	 && h_errno == NETDB_INTERNAL
462 	 && (errval = errno) == ERANGE)
463     if (!scratch_buffer_grow (&tmpbuf))
464       {
465 	/* We ran out of memory.  We cannot do anything but sending a
466 	   negative response.  In reality this should never
467 	   happen.  */
468 	hst = NULL;
469 	/* We set the error to indicate this is (possibly) a temporary
470 	   error and that it does not mean the entry is not
471 	   available at all.  */
472 	h_errno = TRY_AGAIN;
473 	errval = EAGAIN;
474 	break;
475       }
476 
477   time_t timeout = cache_addhst (db, fd, req, key, hst, uid, he, dh,
478 				 h_errno == TRY_AGAIN ? errval : 0, ttl);
479   scratch_buffer_free (&tmpbuf);
480   return timeout;
481 }
482 
483 
484 void
addhstbyname(struct database_dyn * db,int fd,request_header * req,void * key,uid_t uid)485 addhstbyname (struct database_dyn *db, int fd, request_header *req,
486 	      void *key, uid_t uid)
487 {
488   addhstbyX (db, fd, req, key, uid, NULL, NULL);
489 }
490 
491 
492 time_t
readdhstbyname(struct database_dyn * db,struct hashentry * he,struct datahead * dh)493 readdhstbyname (struct database_dyn *db, struct hashentry *he,
494 		struct datahead *dh)
495 {
496   request_header req =
497     {
498       .type = GETHOSTBYNAME,
499       .key_len = he->len
500     };
501 
502   return addhstbyX (db, -1, &req, db->data + he->key, he->owner, he, dh);
503 }
504 
505 
506 void
addhstbyaddr(struct database_dyn * db,int fd,request_header * req,void * key,uid_t uid)507 addhstbyaddr (struct database_dyn *db, int fd, request_header *req,
508 	      void *key, uid_t uid)
509 {
510   addhstbyX (db, fd, req, key, uid, NULL, NULL);
511 }
512 
513 
514 time_t
readdhstbyaddr(struct database_dyn * db,struct hashentry * he,struct datahead * dh)515 readdhstbyaddr (struct database_dyn *db, struct hashentry *he,
516 		struct datahead *dh)
517 {
518   request_header req =
519     {
520       .type = GETHOSTBYADDR,
521       .key_len = he->len
522     };
523 
524   return addhstbyX (db, -1, &req, db->data + he->key, he->owner, he, dh);
525 }
526 
527 
528 void
addhstbynamev6(struct database_dyn * db,int fd,request_header * req,void * key,uid_t uid)529 addhstbynamev6 (struct database_dyn *db, int fd, request_header *req,
530 		void *key, uid_t uid)
531 {
532   addhstbyX (db, fd, req, key, uid, NULL, NULL);
533 }
534 
535 
536 time_t
readdhstbynamev6(struct database_dyn * db,struct hashentry * he,struct datahead * dh)537 readdhstbynamev6 (struct database_dyn *db, struct hashentry *he,
538 		  struct datahead *dh)
539 {
540   request_header req =
541     {
542       .type = GETHOSTBYNAMEv6,
543       .key_len = he->len
544     };
545 
546   return addhstbyX (db, -1, &req, db->data + he->key, he->owner, he, dh);
547 }
548 
549 
550 void
addhstbyaddrv6(struct database_dyn * db,int fd,request_header * req,void * key,uid_t uid)551 addhstbyaddrv6 (struct database_dyn *db, int fd, request_header *req,
552 		void *key, uid_t uid)
553 {
554   addhstbyX (db, fd, req, key, uid, NULL, NULL);
555 }
556 
557 
558 time_t
readdhstbyaddrv6(struct database_dyn * db,struct hashentry * he,struct datahead * dh)559 readdhstbyaddrv6 (struct database_dyn *db, struct hashentry *he,
560 		  struct datahead *dh)
561 {
562   request_header req =
563     {
564       .type = GETHOSTBYADDRv6,
565       .key_len = he->len
566     };
567 
568   return addhstbyX (db, -1, &req, db->data + he->key, he->owner, he, dh);
569 }
570