]> git.ipfire.org Git - thirdparty/glibc.git/blame - nscd/connections.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / nscd / connections.c
CommitLineData
67479a70 1/* Inner loops of cache daemon.
b168057a 2 Copyright (C) 1998-2015 Free Software Foundation, Inc.
d67281a7 3 This file is part of the GNU C Library.
67479a70 4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
d67281a7 5
43bc8ac6 6 This program is free software; you can redistribute it and/or modify
2e2efe65
RM
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; version 2 of the License, or
9 (at your option) any later version.
d67281a7 10
43bc8ac6 11 This program is distributed in the hope that it will be useful,
d67281a7 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
43bc8ac6
UD
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
d67281a7 15
43bc8ac6 16 You should have received a copy of the GNU General Public License
59ba27a6 17 along with this program; if not, see <http://www.gnu.org/licenses/>. */
d67281a7 18
4401d759 19#include <alloca.h>
67479a70 20#include <assert.h>
0fdb4f42 21#include <atomic.h>
d67281a7 22#include <error.h>
67479a70 23#include <errno.h>
d6db0975 24#include <fcntl.h>
057685e4 25#include <grp.h>
3a2c0242 26#include <ifaddrs.h>
a95a08b4 27#include <libintl.h>
d67281a7 28#include <pthread.h>
057685e4 29#include <pwd.h>
482bbeb9 30#include <resolv.h>
057685e4 31#include <stdio.h>
d67281a7
UD
32#include <stdlib.h>
33#include <unistd.h>
e054f494 34#include <stdint.h>
8d8c6efa 35#include <arpa/inet.h>
3a2c0242 36#ifdef HAVE_NETLINK
432d41ce
UD
37# include <linux/netlink.h>
38# include <linux/rtnetlink.h>
3a2c0242 39#endif
fc03df7a
UD
40#ifdef HAVE_EPOLL
41# include <sys/epoll.h>
42#endif
5228ba2f
UD
43#ifdef HAVE_INOTIFY
44# include <sys/inotify.h>
45#endif
a95a08b4 46#include <sys/mman.h>
67479a70 47#include <sys/param.h>
a53bad16 48#include <sys/poll.h>
eac10791
UD
49#ifdef HAVE_SENDFILE
50# include <sys/sendfile.h>
51#endif
d67281a7
UD
52#include <sys/socket.h>
53#include <sys/stat.h>
d67281a7
UD
54#include <sys/un.h>
55
56#include "nscd.h"
57#include "dbg_log.h"
74a30a58 58#include "selinux.h"
a0edbb48 59#include <resolv/resolv.h>
37233df9
TS
60
61#include <kernel-features.h>
e7300fef 62#include <libc-internal.h>
a334319f
UD
63
64
057685e4
UD
65/* Support to run nscd as an unprivileged user */
66const char *server_user;
67static uid_t server_uid;
68static gid_t server_gid;
a12ce44f
UD
69const char *stat_user;
70uid_t stat_uid;
057685e4
UD
71static gid_t *server_groups;
72#ifndef NGROUPS
73# define NGROUPS 32
74#endif
a95a08b4 75static int server_ngroups;
057685e4 76
27e82856
UD
77static pthread_attr_t attr;
78
057685e4
UD
79static void begin_drop_privileges (void);
80static void finish_drop_privileges (void);
81
67479a70 82/* Map request type to a string. */
b21fa963 83const char *const serv2str[LASTREQ] =
d67281a7 84{
67479a70
UD
85 [GETPWBYNAME] = "GETPWBYNAME",
86 [GETPWBYUID] = "GETPWBYUID",
87 [GETGRBYNAME] = "GETGRBYNAME",
88 [GETGRBYGID] = "GETGRBYGID",
89 [GETHOSTBYNAME] = "GETHOSTBYNAME",
90 [GETHOSTBYNAMEv6] = "GETHOSTBYNAMEv6",
91 [GETHOSTBYADDR] = "GETHOSTBYADDR",
92 [GETHOSTBYADDRv6] = "GETHOSTBYADDRv6",
93 [SHUTDOWN] = "SHUTDOWN",
756409c4 94 [GETSTAT] = "GETSTAT",
c207f23b
UD
95 [INVALIDATE] = "INVALIDATE",
96 [GETFDPW] = "GETFDPW",
97 [GETFDGR] = "GETFDGR",
d19687d6 98 [GETFDHST] = "GETFDHST",
f7e7a396 99 [GETAI] = "GETAI",
b21fa963
UD
100 [INITGROUPS] = "INITGROUPS",
101 [GETSERVBYNAME] = "GETSERVBYNAME",
102 [GETSERVBYPORT] = "GETSERVBYPORT",
684ae515
UD
103 [GETFDSERV] = "GETFDSERV",
104 [GETNETGRENT] = "GETNETGRENT",
105 [INNETGR] = "INNETGR",
106 [GETFDNETGR] = "GETFDNETGR"
67479a70
UD
107};
108
109/* The control data structures for the services. */
a95a08b4 110struct database_dyn dbs[lastdb] =
67479a70
UD
111{
112 [pwddb] = {
c2e13112 113 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
ffb1b882 114 .prune_lock = PTHREAD_MUTEX_INITIALIZER,
cd72adeb 115 .prune_run_lock = PTHREAD_MUTEX_INITIALIZER,
c2e13112
RM
116 .enabled = 0,
117 .check_file = 1,
a95a08b4 118 .persistent = 0,
797ed6f7 119 .propagate = 1,
c207f23b 120 .shared = 0,
2c210d1e 121 .max_db_size = DEFAULT_MAX_DB_SIZE,
27c377dd 122 .suggested_module = DEFAULT_SUGGESTED_MODULE,
a95a08b4 123 .db_filename = _PATH_NSCD_PASSWD_DB,
c2e13112
RM
124 .disabled_iov = &pwd_iov_disabled,
125 .postimeout = 3600,
a95a08b4
UD
126 .negtimeout = 20,
127 .wr_fd = -1,
128 .ro_fd = -1,
129 .mmap_used = false
67479a70
UD
130 },
131 [grpdb] = {
c2e13112 132 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
ffb1b882 133 .prune_lock = PTHREAD_MUTEX_INITIALIZER,
cd72adeb 134 .prune_run_lock = PTHREAD_MUTEX_INITIALIZER,
c2e13112
RM
135 .enabled = 0,
136 .check_file = 1,
a95a08b4 137 .persistent = 0,
797ed6f7 138 .propagate = 1,
c207f23b 139 .shared = 0,
2c210d1e 140 .max_db_size = DEFAULT_MAX_DB_SIZE,
27c377dd 141 .suggested_module = DEFAULT_SUGGESTED_MODULE,
a95a08b4 142 .db_filename = _PATH_NSCD_GROUP_DB,
c2e13112
RM
143 .disabled_iov = &grp_iov_disabled,
144 .postimeout = 3600,
a95a08b4
UD
145 .negtimeout = 60,
146 .wr_fd = -1,
147 .ro_fd = -1,
148 .mmap_used = false
67479a70
UD
149 },
150 [hstdb] = {
c2e13112 151 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
ffb1b882 152 .prune_lock = PTHREAD_MUTEX_INITIALIZER,
cd72adeb 153 .prune_run_lock = PTHREAD_MUTEX_INITIALIZER,
c2e13112
RM
154 .enabled = 0,
155 .check_file = 1,
a95a08b4 156 .persistent = 0,
797ed6f7 157 .propagate = 0, /* Not used. */
c207f23b 158 .shared = 0,
2c210d1e 159 .max_db_size = DEFAULT_MAX_DB_SIZE,
27c377dd 160 .suggested_module = DEFAULT_SUGGESTED_MODULE,
a95a08b4 161 .db_filename = _PATH_NSCD_HOSTS_DB,
c2e13112
RM
162 .disabled_iov = &hst_iov_disabled,
163 .postimeout = 3600,
a95a08b4
UD
164 .negtimeout = 20,
165 .wr_fd = -1,
166 .ro_fd = -1,
167 .mmap_used = false
b21fa963
UD
168 },
169 [servdb] = {
170 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
ffb1b882 171 .prune_lock = PTHREAD_MUTEX_INITIALIZER,
cd72adeb 172 .prune_run_lock = PTHREAD_MUTEX_INITIALIZER,
b21fa963
UD
173 .enabled = 0,
174 .check_file = 1,
175 .persistent = 0,
176 .propagate = 0, /* Not used. */
177 .shared = 0,
178 .max_db_size = DEFAULT_MAX_DB_SIZE,
27c377dd 179 .suggested_module = DEFAULT_SUGGESTED_MODULE,
b21fa963
UD
180 .db_filename = _PATH_NSCD_SERVICES_DB,
181 .disabled_iov = &serv_iov_disabled,
182 .postimeout = 28800,
183 .negtimeout = 20,
184 .wr_fd = -1,
185 .ro_fd = -1,
186 .mmap_used = false
684ae515
UD
187 },
188 [netgrdb] = {
189 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
190 .prune_lock = PTHREAD_MUTEX_INITIALIZER,
191 .prune_run_lock = PTHREAD_MUTEX_INITIALIZER,
192 .enabled = 0,
193 .check_file = 1,
194 .persistent = 0,
195 .propagate = 0, /* Not used. */
196 .shared = 0,
197 .max_db_size = DEFAULT_MAX_DB_SIZE,
198 .suggested_module = DEFAULT_SUGGESTED_MODULE,
199 .db_filename = _PATH_NSCD_NETGROUP_DB,
200 .disabled_iov = &netgroup_iov_disabled,
201 .postimeout = 28800,
202 .negtimeout = 20,
203 .wr_fd = -1,
204 .ro_fd = -1,
205 .mmap_used = false
67479a70
UD
206 }
207};
d67281a7 208
a95a08b4
UD
209
210/* Mapping of request type to database. */
9691d83c 211static struct
a95a08b4 212{
9691d83c
UD
213 bool data_request;
214 struct database_dyn *db;
000b027e 215} const reqinfo[LASTREQ] =
9691d83c
UD
216{
217 [GETPWBYNAME] = { true, &dbs[pwddb] },
218 [GETPWBYUID] = { true, &dbs[pwddb] },
219 [GETGRBYNAME] = { true, &dbs[grpdb] },
220 [GETGRBYGID] = { true, &dbs[grpdb] },
221 [GETHOSTBYNAME] = { true, &dbs[hstdb] },
222 [GETHOSTBYNAMEv6] = { true, &dbs[hstdb] },
223 [GETHOSTBYADDR] = { true, &dbs[hstdb] },
224 [GETHOSTBYADDRv6] = { true, &dbs[hstdb] },
225 [SHUTDOWN] = { false, NULL },
226 [GETSTAT] = { false, NULL },
227 [SHUTDOWN] = { false, NULL },
228 [GETFDPW] = { false, &dbs[pwddb] },
229 [GETFDGR] = { false, &dbs[grpdb] },
230 [GETFDHST] = { false, &dbs[hstdb] },
231 [GETAI] = { true, &dbs[hstdb] },
232 [INITGROUPS] = { true, &dbs[grpdb] },
233 [GETSERVBYNAME] = { true, &dbs[servdb] },
234 [GETSERVBYPORT] = { true, &dbs[servdb] },
684ae515
UD
235 [GETFDSERV] = { false, &dbs[servdb] },
236 [GETNETGRENT] = { true, &dbs[netgrdb] },
237 [INNETGR] = { true, &dbs[netgrdb] },
238 [GETFDNETGR] = { false, &dbs[netgrdb] }
a95a08b4
UD
239};
240
241
27e82856 242/* Initial number of threads to use. */
67479a70 243int nthreads = -1;
27e82856
UD
244/* Maximum number of threads to use. */
245int max_nthreads = 32;
d67281a7 246
67479a70
UD
247/* Socket for incoming connections. */
248static int sock;
d67281a7 249
5228ba2f
UD
250#ifdef HAVE_INOTIFY
251/* Inotify descriptor. */
319b9ad4 252int inotify_fd = -1;
5228ba2f
UD
253#endif
254
3a2c0242
UD
255#ifdef HAVE_NETLINK
256/* Descriptor for netlink status updates. */
257static int nl_status_fd = -1;
258#endif
259
3ff2c948
UD
260#ifndef __ASSUME_SOCK_CLOEXEC
261/* Negative if SOCK_CLOEXEC is not supported, positive if it is, zero
262 before be know the result. */
263static int have_sock_cloexec;
f93fc0b7
UD
264#endif
265#ifndef __ASSUME_ACCEPT4
266static int have_accept4;
3ff2c948
UD
267#endif
268
0fdb4f42
UD
269/* Number of times clients had to wait. */
270unsigned long int client_queued;
271
d67281a7 272
d2dc7d84
UD
273ssize_t
274writeall (int fd, const void *buf, size_t len)
275{
276 size_t n = len;
277 ssize_t ret;
278 do
279 {
2c210d1e 280 ret = TEMP_FAILURE_RETRY (send (fd, buf, n, MSG_NOSIGNAL));
d2dc7d84
UD
281 if (ret <= 0)
282 break;
283 buf = (const char *) buf + ret;
284 n -= ret;
285 }
286 while (n > 0);
287 return ret < 0 ? ret : len - n;
288}
289
290
bd547139
UD
291#ifdef HAVE_SENDFILE
292ssize_t
293sendfileall (int tofd, int fromfd, off_t off, size_t len)
294{
295 ssize_t n = len;
296 ssize_t ret;
297
298 do
299 {
300 ret = TEMP_FAILURE_RETRY (sendfile (tofd, fromfd, &off, n));
301 if (ret <= 0)
302 break;
303 n -= ret;
304 }
305 while (n > 0);
306 return ret < 0 ? ret : len - n;
307}
308#endif
309
310
dc4bb1c2
UD
311enum usekey
312 {
313 use_not = 0,
314 /* The following three are not really used, they are symbolic constants. */
315 use_first = 16,
316 use_begin = 32,
317 use_end = 64,
318
319 use_he = 1,
320 use_he_begin = use_he | use_begin,
321 use_he_end = use_he | use_end,
dc4bb1c2
UD
322 use_data = 3,
323 use_data_begin = use_data | use_begin,
324 use_data_end = use_data | use_end,
325 use_data_first = use_data_begin | use_first
326 };
327
328
329static int
330check_use (const char *data, nscd_ssize_t first_free, uint8_t *usemap,
331 enum usekey use, ref_t start, size_t len)
332{
333 assert (len >= 2);
334
335 if (start > first_free || start + len > first_free
336 || (start & BLOCK_ALIGN_M1))
337 return 0;
338
339 if (usemap[start] == use_not)
340 {
341 /* Add the start marker. */
342 usemap[start] = use | use_begin;
343 use &= ~use_first;
344
345 while (--len > 0)
346 if (usemap[++start] != use_not)
347 return 0;
348 else
349 usemap[start] = use;
350
351 /* Add the end marker. */
352 usemap[start] = use | use_end;
353 }
354 else if ((usemap[start] & ~use_first) == ((use | use_begin) & ~use_first))
355 {
356 /* Hash entries can't be shared. */
357 if (use == use_he)
358 return 0;
359
360 usemap[start] |= (use & use_first);
361 use &= ~use_first;
362
363 while (--len > 1)
364 if (usemap[++start] != use)
365 return 0;
366
367 if (usemap[++start] != (use | use_end))
368 return 0;
369 }
370 else
371 /* Points to a wrong object or somewhere in the middle. */
372 return 0;
373
374 return 1;
375}
376
377
378/* Verify data in persistent database. */
379static int
380verify_persistent_db (void *mem, struct database_pers_head *readhead, int dbnr)
381{
684ae515
UD
382 assert (dbnr == pwddb || dbnr == grpdb || dbnr == hstdb || dbnr == servdb
383 || dbnr == netgrdb);
dc4bb1c2
UD
384
385 time_t now = time (NULL);
386
387 struct database_pers_head *head = mem;
388 struct database_pers_head head_copy = *head;
389
390 /* Check that the header that was read matches the head in the database. */
27c377dd 391 if (memcmp (head, readhead, sizeof (*head)) != 0)
dc4bb1c2
UD
392 return 0;
393
394 /* First some easy tests: make sure the database header is sane. */
395 if (head->version != DB_VERSION
396 || head->header_size != sizeof (*head)
397 /* We allow a timestamp to be one hour ahead of the current time.
398 This should cover daylight saving time changes. */
399 || head->timestamp > now + 60 * 60 + 60
400 || (head->gc_cycle & 1)
27c377dd 401 || head->module == 0
dc4bb1c2
UD
402 || (size_t) head->module > INT32_MAX / sizeof (ref_t)
403 || (size_t) head->data_size > INT32_MAX - head->module * sizeof (ref_t)
404 || head->first_free < 0
405 || head->first_free > head->data_size
406 || (head->first_free & BLOCK_ALIGN_M1) != 0
407 || head->maxnentries < 0
408 || head->maxnsearched < 0)
409 return 0;
410
411 uint8_t *usemap = calloc (head->first_free, 1);
412 if (usemap == NULL)
413 return 0;
414
415 const char *data = (char *) &head->array[roundup (head->module,
416 ALIGN / sizeof (ref_t))];
417
418 nscd_ssize_t he_cnt = 0;
419 for (nscd_ssize_t cnt = 0; cnt < head->module; ++cnt)
420 {
a6fa5328
UD
421 ref_t trail = head->array[cnt];
422 ref_t work = trail;
423 int tick = 0;
dc4bb1c2
UD
424
425 while (work != ENDREF)
426 {
427 if (! check_use (data, head->first_free, usemap, use_he, work,
428 sizeof (struct hashentry)))
429 goto fail;
430
431 /* Now we know we can dereference the record. */
432 struct hashentry *here = (struct hashentry *) (data + work);
433
434 ++he_cnt;
435
436 /* Make sure the record is for this type of service. */
437 if (here->type >= LASTREQ
000b027e 438 || reqinfo[here->type].db != &dbs[dbnr])
dc4bb1c2
UD
439 goto fail;
440
441 /* Validate boolean field value. */
442 if (here->first != false && here->first != true)
443 goto fail;
444
445 if (here->len < 0)
446 goto fail;
447
448 /* Now the data. */
449 if (here->packet < 0
450 || here->packet > head->first_free
451 || here->packet + sizeof (struct datahead) > head->first_free)
452 goto fail;
453
454 struct datahead *dh = (struct datahead *) (data + here->packet);
455
456 if (! check_use (data, head->first_free, usemap,
457 use_data | (here->first ? use_first : 0),
458 here->packet, dh->allocsize))
459 goto fail;
460
461 if (dh->allocsize < sizeof (struct datahead)
462 || dh->recsize > dh->allocsize
463 || (dh->notfound != false && dh->notfound != true)
464 || (dh->usable != false && dh->usable != true))
465 goto fail;
466
467 if (here->key < here->packet + sizeof (struct datahead)
468 || here->key > here->packet + dh->allocsize
469 || here->key + here->len > here->packet + dh->allocsize)
2aac0a86 470 goto fail;
dc4bb1c2
UD
471
472 work = here->next;
50607309 473
a6fa5328 474 if (work == trail)
50607309
UD
475 /* A circular list, this must not happen. */
476 goto fail;
a6fa5328
UD
477 if (tick)
478 trail = ((struct hashentry *) (data + trail))->next;
479 tick = 1 - tick;
dc4bb1c2
UD
480 }
481 }
482
483 if (he_cnt != head->nentries)
484 goto fail;
485
486 /* See if all data and keys had at least one reference from
487 he->first == true hashentry. */
488 for (ref_t idx = 0; idx < head->first_free; ++idx)
489 {
dc4bb1c2
UD
490 if (usemap[idx] == use_data_begin)
491 goto fail;
492 }
493
494 /* Finally, make sure the database hasn't changed since the first test. */
495 if (memcmp (mem, &head_copy, sizeof (*head)) != 0)
496 goto fail;
497
498 free (usemap);
499 return 1;
500
501fail:
502 free (usemap);
503 return 0;
504}
505
506
d7e23b02
UD
507#ifdef O_CLOEXEC
508# define EXTRA_O_FLAGS O_CLOEXEC
509#else
510# define EXTRA_O_FLAGS 0
511#endif
512
513
a334319f
UD
514/* Initialize database information structures. */
515void
516nscd_init (void)
0ecb606c 517{
057685e4
UD
518 /* Look up unprivileged uid/gid/groups before we start listening on the
519 socket */
520 if (server_user != NULL)
521 begin_drop_privileges ();
522
67479a70
UD
523 if (nthreads == -1)
524 /* No configuration for this value, assume a default. */
ffb1b882 525 nthreads = 4;
d67281a7 526
d2dc7d84 527 for (size_t cnt = 0; cnt < lastdb; ++cnt)
67479a70 528 if (dbs[cnt].enabled)
9db29cde 529 {
67479a70 530 pthread_rwlock_init (&dbs[cnt].lock, NULL);
a95a08b4 531 pthread_mutex_init (&dbs[cnt].memlock, NULL);
264d5b94 532
a95a08b4 533 if (dbs[cnt].persistent)
e09edf23 534 {
a95a08b4 535 /* Try to open the appropriate file on disk. */
d7e23b02 536 int fd = open (dbs[cnt].db_filename, O_RDWR | EXTRA_O_FLAGS);
a95a08b4
UD
537 if (fd != -1)
538 {
27c377dd 539 char *msg = NULL;
a95a08b4
UD
540 struct stat64 st;
541 void *mem;
542 size_t total;
543 struct database_pers_head head;
544 ssize_t n = TEMP_FAILURE_RETRY (read (fd, &head,
545 sizeof (head)));
546 if (n != sizeof (head) || fstat64 (fd, &st) != 0)
547 {
27c377dd
UD
548 fail_db_errno:
549 /* The code is single-threaded at this point so
550 using strerror is just fine. */
551 msg = strerror (errno);
a95a08b4
UD
552 fail_db:
553 dbg_log (_("invalid persistent database file \"%s\": %s"),
27c377dd 554 dbs[cnt].db_filename, msg);
dc4bb1c2 555 unlink (dbs[cnt].db_filename);
a95a08b4
UD
556 }
557 else if (head.module == 0 && head.data_size == 0)
558 {
27c377dd
UD
559 /* The file has been created, but the head has not
560 been initialized yet. */
561 msg = _("uninitialized header");
562 goto fail_db;
a95a08b4
UD
563 }
564 else if (head.header_size != (int) sizeof (head))
565 {
27c377dd
UD
566 msg = _("header size does not match");
567 goto fail_db;
a95a08b4
UD
568 }
569 else if ((total = (sizeof (head)
c207f23b 570 + roundup (head.module * sizeof (ref_t),
a95a08b4
UD
571 ALIGN)
572 + head.data_size))
dc4bb1c2
UD
573 > st.st_size
574 || total < sizeof (head))
a95a08b4 575 {
27c377dd
UD
576 msg = _("file size does not match");
577 goto fail_db;
a95a08b4 578 }
2c210d1e
UD
579 /* Note we map with the maximum size allowed for the
580 database. This is likely much larger than the
581 actual file size. This is OK on most OSes since
582 extensions of the underlying file will
583 automatically translate more pages available for
584 memory access. */
585 else if ((mem = mmap (NULL, dbs[cnt].max_db_size,
586 PROT_READ | PROT_WRITE,
587 MAP_SHARED, fd, 0))
588 == MAP_FAILED)
27c377dd 589 goto fail_db_errno;
dc4bb1c2
UD
590 else if (!verify_persistent_db (mem, &head, cnt))
591 {
592 munmap (mem, total);
27c377dd
UD
593 msg = _("verification failed");
594 goto fail_db;
dc4bb1c2 595 }
a95a08b4
UD
596 else
597 {
598 /* Success. We have the database. */
599 dbs[cnt].head = mem;
600 dbs[cnt].memsize = total;
601 dbs[cnt].data = (char *)
602 &dbs[cnt].head->array[roundup (dbs[cnt].head->module,
603 ALIGN / sizeof (ref_t))];
604 dbs[cnt].mmap_used = true;
605
606 if (dbs[cnt].suggested_module > head.module)
607 dbg_log (_("suggested size of table for database %s larger than the persistent database's table"),
608 dbnames[cnt]);
609
610 dbs[cnt].wr_fd = fd;
611 fd = -1;
612 /* We also need a read-only descriptor. */
d13a3c57
UD
613 if (dbs[cnt].shared)
614 {
d7e23b02
UD
615 dbs[cnt].ro_fd = open (dbs[cnt].db_filename,
616 O_RDONLY | EXTRA_O_FLAGS);
d13a3c57
UD
617 if (dbs[cnt].ro_fd == -1)
618 dbg_log (_("\
a95a08b4 619cannot create read-only descriptor for \"%s\"; no mmap"),
d13a3c57
UD
620 dbs[cnt].db_filename);
621 }
a95a08b4
UD
622
623 // XXX Shall we test whether the descriptors actually
624 // XXX point to the same file?
625 }
626
627 /* Close the file descriptors in case something went
628 wrong in which case the variable have not been
629 assigned -1. */
630 if (fd != -1)
631 close (fd);
632 }
31d322a2 633 else if (errno == EACCES)
532a6035
SP
634 do_exit (EXIT_FAILURE, 0, _("cannot access '%s'"),
635 dbs[cnt].db_filename);
a95a08b4
UD
636 }
637
638 if (dbs[cnt].head == NULL)
639 {
640 /* No database loaded. Allocate the data structure,
641 possibly on disk. */
642 struct database_pers_head head;
643 size_t total = (sizeof (head)
644 + roundup (dbs[cnt].suggested_module
645 * sizeof (ref_t), ALIGN)
646 + (dbs[cnt].suggested_module
647 * DEFAULT_DATASIZE_PER_BUCKET));
648
649 /* Try to create the database. If we do not need a
650 persistent database create a temporary file. */
651 int fd;
652 int ro_fd = -1;
653 if (dbs[cnt].persistent)
654 {
655 fd = open (dbs[cnt].db_filename,
d7e23b02 656 O_RDWR | O_CREAT | O_EXCL | O_TRUNC | EXTRA_O_FLAGS,
a95a08b4 657 S_IRUSR | S_IWUSR);
d13a3c57 658 if (fd != -1 && dbs[cnt].shared)
d7e23b02
UD
659 ro_fd = open (dbs[cnt].db_filename,
660 O_RDONLY | EXTRA_O_FLAGS);
a95a08b4
UD
661 }
662 else
663 {
a8a58967 664 char fname[] = _PATH_NSCD_XYZ_DB_TMP;
d7e23b02 665 fd = mkostemp (fname, EXTRA_O_FLAGS);
a95a08b4
UD
666
667 /* We do not need the file name anymore after we
668 opened another file descriptor in read-only mode. */
5ca3d19c 669 if (fd != -1)
a95a08b4 670 {
5ca3d19c 671 if (dbs[cnt].shared)
d7e23b02 672 ro_fd = open (fname, O_RDONLY | EXTRA_O_FLAGS);
a95a08b4
UD
673
674 unlink (fname);
675 }
676 }
677
678 if (fd == -1)
679 {
680 if (errno == EEXIST)
681 {
682 dbg_log (_("database for %s corrupted or simultaneously used; remove %s manually if necessary and restart"),
683 dbnames[cnt], dbs[cnt].db_filename);
532a6035 684 do_exit (1, 0, NULL);
a95a08b4
UD
685 }
686
687 if (dbs[cnt].persistent)
688 dbg_log (_("cannot create %s; no persistent database used"),
689 dbs[cnt].db_filename);
690 else
691 dbg_log (_("cannot create %s; no sharing possible"),
692 dbs[cnt].db_filename);
693
694 dbs[cnt].persistent = 0;
695 // XXX remember: no mmap
696 }
697 else
698 {
699 /* Tell the user if we could not create the read-only
700 descriptor. */
d13a3c57 701 if (ro_fd == -1 && dbs[cnt].shared)
a95a08b4
UD
702 dbg_log (_("\
703cannot create read-only descriptor for \"%s\"; no mmap"),
704 dbs[cnt].db_filename);
705
a31ee4b3
SP
706 /* Before we create the header, initialize the hash
707 table. That way if we get interrupted while writing
a95a08b4
UD
708 the header we can recognize a partially initialized
709 database. */
710 size_t ps = sysconf (_SC_PAGESIZE);
711 char tmpbuf[ps];
712 assert (~ENDREF == 0);
713 memset (tmpbuf, '\xff', ps);
714
715 size_t remaining = dbs[cnt].suggested_module * sizeof (ref_t);
716 off_t offset = sizeof (head);
717
718 size_t towrite;
719 if (offset % ps != 0)
720 {
721 towrite = MIN (remaining, ps - (offset % ps));
233399bc
UD
722 if (pwrite (fd, tmpbuf, towrite, offset) != towrite)
723 goto write_fail;
a95a08b4
UD
724 offset += towrite;
725 remaining -= towrite;
726 }
727
728 while (remaining > ps)
729 {
233399bc
UD
730 if (pwrite (fd, tmpbuf, ps, offset) == -1)
731 goto write_fail;
a95a08b4
UD
732 offset += ps;
733 remaining -= ps;
734 }
735
233399bc
UD
736 if (remaining > 0
737 && pwrite (fd, tmpbuf, remaining, offset) != remaining)
738 goto write_fail;
a95a08b4
UD
739
740 /* Create the header of the file. */
741 struct database_pers_head head =
742 {
743 .version = DB_VERSION,
744 .header_size = sizeof (head),
745 .module = dbs[cnt].suggested_module,
746 .data_size = (dbs[cnt].suggested_module
747 * DEFAULT_DATASIZE_PER_BUCKET),
748 .first_free = 0
749 };
750 void *mem;
751
752 if ((TEMP_FAILURE_RETRY (write (fd, &head, sizeof (head)))
753 != sizeof (head))
2c210d1e
UD
754 || (TEMP_FAILURE_RETRY_VAL (posix_fallocate (fd, 0, total))
755 != 0)
756 || (mem = mmap (NULL, dbs[cnt].max_db_size,
757 PROT_READ | PROT_WRITE,
a95a08b4
UD
758 MAP_SHARED, fd, 0)) == MAP_FAILED)
759 {
233399bc 760 write_fail:
a95a08b4
UD
761 unlink (dbs[cnt].db_filename);
762 dbg_log (_("cannot write to database file %s: %s"),
763 dbs[cnt].db_filename, strerror (errno));
764 dbs[cnt].persistent = 0;
765 }
766 else
767 {
768 /* Success. */
769 dbs[cnt].head = mem;
770 dbs[cnt].data = (char *)
771 &dbs[cnt].head->array[roundup (dbs[cnt].head->module,
772 ALIGN / sizeof (ref_t))];
773 dbs[cnt].memsize = total;
774 dbs[cnt].mmap_used = true;
775
776 /* Remember the descriptors. */
777 dbs[cnt].wr_fd = fd;
778 dbs[cnt].ro_fd = ro_fd;
779 fd = -1;
780 ro_fd = -1;
781 }
782
783 if (fd != -1)
784 close (fd);
785 if (ro_fd != -1)
786 close (ro_fd);
787 }
788 }
789
d7e23b02
UD
790#if !defined O_CLOEXEC || !defined __ASSUME_O_CLOEXEC
791 /* We do not check here whether the O_CLOEXEC provided to the
792 open call was successful or not. The two fcntl calls are
793 only performed once each per process start-up and therefore
794 is not noticeable at all. */
4401d759
UD
795 if (paranoia
796 && ((dbs[cnt].wr_fd != -1
797 && fcntl (dbs[cnt].wr_fd, F_SETFD, FD_CLOEXEC) == -1)
798 || (dbs[cnt].ro_fd != -1
799 && fcntl (dbs[cnt].ro_fd, F_SETFD, FD_CLOEXEC) == -1)))
800 {
801 dbg_log (_("\
802cannot set socket to close on exec: %s; disabling paranoia mode"),
803 strerror (errno));
804 paranoia = 0;
805 }
d7e23b02 806#endif
4401d759 807
a95a08b4
UD
808 if (dbs[cnt].head == NULL)
809 {
810 /* We do not use the persistent database. Just
811 create an in-memory data structure. */
812 assert (! dbs[cnt].persistent);
813
814 dbs[cnt].head = xmalloc (sizeof (struct database_pers_head)
815 + (dbs[cnt].suggested_module
816 * sizeof (ref_t)));
25059769 817 memset (dbs[cnt].head, '\0', sizeof (struct database_pers_head));
a95a08b4
UD
818 assert (~ENDREF == 0);
819 memset (dbs[cnt].head->array, '\xff',
820 dbs[cnt].suggested_module * sizeof (ref_t));
821 dbs[cnt].head->module = dbs[cnt].suggested_module;
822 dbs[cnt].head->data_size = (DEFAULT_DATASIZE_PER_BUCKET
823 * dbs[cnt].head->module);
824 dbs[cnt].data = xmalloc (dbs[cnt].head->data_size);
825 dbs[cnt].head->first_free = 0;
c207f23b
UD
826
827 dbs[cnt].shared = 0;
828 assert (dbs[cnt].ro_fd == -1);
e09edf23 829 }
67479a70 830 }
d67281a7
UD
831
832 /* Create the socket. */
3ff2c948
UD
833#ifndef __ASSUME_SOCK_CLOEXEC
834 sock = -1;
835 if (have_sock_cloexec >= 0)
836#endif
837 {
838 sock = socket (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
bd7f4857 839#ifndef __ASSUME_SOCK_CLOEXEC
3ff2c948
UD
840 if (have_sock_cloexec == 0)
841 have_sock_cloexec = sock != -1 || errno != EINVAL ? 1 : -1;
842#endif
843 }
844#ifndef __ASSUME_SOCK_CLOEXEC
845 if (have_sock_cloexec < 0)
846 sock = socket (AF_UNIX, SOCK_STREAM, 0);
847#endif
67479a70 848 if (sock < 0)
d67281a7 849 {
67479a70 850 dbg_log (_("cannot open socket: %s"), strerror (errno));
532a6035 851 do_exit (errno == EACCES ? 4 : 1, 0, NULL);
d67281a7
UD
852 }
853 /* Bind a name to the socket. */
d2dc7d84 854 struct sockaddr_un sock_addr;
d67281a7
UD
855 sock_addr.sun_family = AF_UNIX;
856 strcpy (sock_addr.sun_path, _PATH_NSCDSOCKET);
67479a70 857 if (bind (sock, (struct sockaddr *) &sock_addr, sizeof (sock_addr)) < 0)
d67281a7
UD
858 {
859 dbg_log ("%s: %s", _PATH_NSCDSOCKET, strerror (errno));
532a6035 860 do_exit (errno == EACCES ? 4 : 1, 0, NULL);
d67281a7 861 }
67479a70 862
3ff2c948
UD
863#ifndef __ASSUME_SOCK_CLOEXEC
864 if (have_sock_cloexec < 0)
4401d759 865 {
3ff2c948
UD
866 /* We don't want to get stuck on accept. */
867 int fl = fcntl (sock, F_GETFL);
868 if (fl == -1 || fcntl (sock, F_SETFL, fl | O_NONBLOCK) == -1)
869 {
870 dbg_log (_("cannot change socket to nonblocking mode: %s"),
871 strerror (errno));
532a6035 872 do_exit (1, 0, NULL);
3ff2c948 873 }
4401d759 874
3ff2c948
UD
875 /* The descriptor needs to be closed on exec. */
876 if (paranoia && fcntl (sock, F_SETFD, FD_CLOEXEC) == -1)
877 {
878 dbg_log (_("cannot set socket to close on exec: %s"),
879 strerror (errno));
532a6035 880 do_exit (1, 0, NULL);
3ff2c948 881 }
4401d759 882 }
3ff2c948 883#endif
d6db0975 884
d67281a7 885 /* Set permissions for the socket. */
a95a08b4 886 chmod (_PATH_NSCDSOCKET, DEFFILEMODE);
d67281a7
UD
887
888 /* Set the socket up to accept connections. */
67479a70 889 if (listen (sock, SOMAXCONN) < 0)
d67281a7 890 {
67479a70
UD
891 dbg_log (_("cannot enable socket to accept connections: %s"),
892 strerror (errno));
532a6035 893 do_exit (1, 0, NULL);
d67281a7 894 }
057685e4 895
3a2c0242
UD
896#ifdef HAVE_NETLINK
897 if (dbs[hstdb].enabled)
898 {
899 /* Try to open netlink socket to monitor network setting changes. */
900 nl_status_fd = socket (AF_NETLINK,
901 SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
902 NETLINK_ROUTE);
903 if (nl_status_fd != -1)
904 {
905 struct sockaddr_nl snl;
906 memset (&snl, '\0', sizeof (snl));
907 snl.nl_family = AF_NETLINK;
908 /* XXX Is this the best set to use? */
909 snl.nl_groups = (RTMGRP_IPV4_IFADDR | RTMGRP_TC | RTMGRP_IPV4_MROUTE
910 | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_RULE
911 | RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_MROUTE
912 | RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFINFO
913 | RTMGRP_IPV6_PREFIX);
914
915 if (bind (nl_status_fd, (struct sockaddr *) &snl, sizeof (snl)) != 0)
916 {
917 close (nl_status_fd);
918 nl_status_fd = -1;
919 }
920 else
921 {
922 /* Start the timestamp process. */
923 dbs[hstdb].head->extra_data[NSCD_HST_IDX_CONF_TIMESTAMP]
924 = __bump_nl_timestamp ();
925
926# ifndef __ASSUME_SOCK_CLOEXEC
927 if (have_sock_cloexec < 0)
928 {
929 /* We don't want to get stuck on accept. */
930 int fl = fcntl (nl_status_fd, F_GETFL);
931 if (fl == -1
932 || fcntl (nl_status_fd, F_SETFL, fl | O_NONBLOCK) == -1)
933 {
934 dbg_log (_("\
935cannot change socket to nonblocking mode: %s"),
936 strerror (errno));
532a6035 937 do_exit (1, 0, NULL);
3a2c0242
UD
938 }
939
940 /* The descriptor needs to be closed on exec. */
941 if (paranoia
942 && fcntl (nl_status_fd, F_SETFD, FD_CLOEXEC) == -1)
943 {
944 dbg_log (_("cannot set socket to close on exec: %s"),
945 strerror (errno));
532a6035 946 do_exit (1, 0, NULL);
3a2c0242
UD
947 }
948 }
949# endif
950 }
951 }
952 }
953#endif
954
319b9ad4 955 /* Change to unprivileged uid/gid/groups if specified in config file */
057685e4
UD
956 if (server_user != NULL)
957 finish_drop_privileges ();
d67281a7
UD
958}
959
67479a70 960
471514d3
CD
961/* Register the file in FINFO as a traced file for the database DBS[DBIX].
962
963 We support registering multiple files per database. Each call to
964 register_traced_file adds to the list of registered files.
965
966 When we prune the database, either through timeout or a request to
967 invalidate, we will check to see if any of the registered files has changed.
968 When we accept new connections to handle a cache request we will also
969 check to see if any of the registered files has changed.
970
971 If we have inotify support then we install an inotify fd to notify us of
972 file deletion or modification, both of which will require we invalidate
973 the cache for the database. Without inotify support we stat the file and
974 store st_mtime to determine if the file has been modified. */
319b9ad4
UD
975void
976register_traced_file (size_t dbidx, struct traced_file *finfo)
977{
471514d3
CD
978 /* If the database is disabled or file checking is disabled
979 then ignore the registration. */
21fd49a9 980 if (! dbs[dbidx].enabled || ! dbs[dbidx].check_file)
319b9ad4
UD
981 return;
982
a1ffb40e 983 if (__glibc_unlikely (debug_level > 0))
319b9ad4
UD
984 dbg_log (_("register trace file %s for database %s"),
985 finfo->fname, dbnames[dbidx]);
986
987#ifdef HAVE_INOTIFY
988 if (inotify_fd < 0
989 || (finfo->inotify_descr = inotify_add_watch (inotify_fd, finfo->fname,
990 IN_DELETE_SELF
991 | IN_MODIFY)) < 0)
992#endif
993 {
994 /* We need the modification date of the file. */
995 struct stat64 st;
996
997 if (stat64 (finfo->fname, &st) < 0)
998 {
999 /* We cannot stat() the file, disable file checking. */
1000 dbg_log (_("cannot stat() file `%s': %s"),
1001 finfo->fname, strerror (errno));
1002 return;
1003 }
1004
1005 finfo->inotify_descr = -1;
1006 finfo->mtime = st.st_mtime;
1007 }
1008
1009 /* Queue up the file name. */
1010 finfo->next = dbs[dbidx].traced_files;
1011 dbs[dbidx].traced_files = finfo;
1012}
1013
1014
67479a70 1015/* Close the connections. */
d67281a7 1016void
67479a70 1017close_sockets (void)
d67281a7 1018{
67479a70
UD
1019 close (sock);
1020}
d67281a7 1021
a12ce44f 1022
756409c4 1023static void
902c4291 1024invalidate_cache (char *key, int fd)
756409c4
UD
1025{
1026 dbtype number;
902c4291 1027 int32_t resp;
756409c4 1028
b21fa963
UD
1029 for (number = pwddb; number < lastdb; ++number)
1030 if (strcmp (key, dbnames[number]) == 0)
1031 {
319b9ad4
UD
1032 if (number == hstdb)
1033 {
1034 struct traced_file *runp = dbs[hstdb].traced_files;
1035 while (runp != NULL)
1036 if (runp->call_res_init)
1037 {
1038 res_init ();
1039 break;
1040 }
1041 else
1042 runp = runp->next;
1043 }
b21fa963 1044 break;
319b9ad4 1045 }
b21fa963
UD
1046
1047 if (number == lastdb)
902c4291
UD
1048 {
1049 resp = EINVAL;
1050 writeall (fd, &resp, sizeof (resp));
1051 return;
1052 }
756409c4 1053
fd665070 1054 if (dbs[number].enabled)
ffb1b882 1055 {
cd72adeb 1056 pthread_mutex_lock (&dbs[number].prune_run_lock);
ffb1b882 1057 prune_cache (&dbs[number], LONG_MAX, fd);
cd72adeb 1058 pthread_mutex_unlock (&dbs[number].prune_run_lock);
ffb1b882 1059 }
902c4291
UD
1060 else
1061 {
1062 resp = 0;
1063 writeall (fd, &resp, sizeof (resp));
1064 }
756409c4
UD
1065}
1066
67479a70 1067
c207f23b
UD
1068#ifdef SCM_RIGHTS
1069static void
1070send_ro_fd (struct database_dyn *db, char *key, int fd)
1071{
1072 /* If we do not have an read-only file descriptor do nothing. */
1073 if (db->ro_fd == -1)
1074 return;
1075
1076 /* We need to send some data along with the descriptor. */
f3c54060
UD
1077 uint64_t mapsize = (db->head->data_size
1078 + roundup (db->head->module * sizeof (ref_t), ALIGN)
1079 + sizeof (struct database_pers_head));
1080 struct iovec iov[2];
c207f23b
UD
1081 iov[0].iov_base = key;
1082 iov[0].iov_len = strlen (key) + 1;
f3c54060
UD
1083 iov[1].iov_base = &mapsize;
1084 iov[1].iov_len = sizeof (mapsize);
c207f23b
UD
1085
1086 /* Prepare the control message to transfer the descriptor. */
a08ab897
UD
1087 union
1088 {
1089 struct cmsghdr hdr;
1090 char bytes[CMSG_SPACE (sizeof (int))];
1091 } buf;
f3c54060 1092 struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 2,
a08ab897
UD
1093 .msg_control = buf.bytes,
1094 .msg_controllen = sizeof (buf) };
c207f23b
UD
1095 struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
1096
1097 cmsg->cmsg_level = SOL_SOCKET;
1098 cmsg->cmsg_type = SCM_RIGHTS;
1099 cmsg->cmsg_len = CMSG_LEN (sizeof (int));
1100
1ac03a1e
UD
1101 int *ip = (int *) CMSG_DATA (cmsg);
1102 *ip = db->ro_fd;
c207f23b
UD
1103
1104 msg.msg_controllen = cmsg->cmsg_len;
1105
1106 /* Send the control message. We repeat when we are interrupted but
1107 everything else is ignored. */
6925ef9a
UD
1108#ifndef MSG_NOSIGNAL
1109# define MSG_NOSIGNAL 0
1110#endif
1111 (void) TEMP_FAILURE_RETRY (sendmsg (fd, &msg, MSG_NOSIGNAL));
c207f23b 1112
a1ffb40e 1113 if (__glibc_unlikely (debug_level > 0))
c207f23b
UD
1114 dbg_log (_("provide access to FD %d, for %s"), db->ro_fd, key);
1115}
1116#endif /* SCM_RIGHTS */
1117
1118
67479a70
UD
1119/* Handle new request. */
1120static void
c52137d3 1121handle_request (int fd, request_header *req, void *key, uid_t uid, pid_t pid)
67479a70 1122{
23700036 1123 if (__builtin_expect (req->version, NSCD_VERSION) != NSCD_VERSION)
d67281a7 1124 {
98e75a1c
UD
1125 if (debug_level > 0)
1126 dbg_log (_("\
67479a70 1127cannot handle old request version %d; current version is %d"),
98e75a1c 1128 req->version, NSCD_VERSION);
d67281a7
UD
1129 return;
1130 }
1131
ffb1b882 1132 /* Perform the SELinux check before we go on to the standard checks. */
000b027e 1133 if (selinux_enabled && nscd_request_avc_has_perm (fd, req->type) != 0)
ffb1b882
UD
1134 {
1135 if (debug_level > 0)
c52137d3
UD
1136 {
1137#ifdef SO_PEERCRED
1138# ifdef PATH_MAX
1139 char buf[PATH_MAX];
1140# else
1141 char buf[4096];
1142# endif
1143
1144 snprintf (buf, sizeof (buf), "/proc/%ld/exe", (long int) pid);
1145 ssize_t n = readlink (buf, buf, sizeof (buf) - 1);
1146
1147 if (n <= 0)
1148 dbg_log (_("\
1149request from %ld not handled due to missing permission"), (long int) pid);
1150 else
1151 {
1152 buf[n] = '\0';
1153 dbg_log (_("\
1154request from '%s' [%ld] not handled due to missing permission"),
1155 buf, (long int) pid);
1156 }
1157#else
1158 dbg_log (_("request not handled due to missing permission"));
1159#endif
1160 }
ffb1b882
UD
1161 return;
1162 }
74a30a58 1163
000b027e 1164 struct database_dyn *db = reqinfo[req->type].db;
a95a08b4 1165
9691d83c 1166 /* See whether we can service the request from the cache. */
000b027e 1167 if (__builtin_expect (reqinfo[req->type].data_request, true))
d67281a7 1168 {
23700036 1169 if (__builtin_expect (debug_level, 0) > 0)
8d8c6efa
UD
1170 {
1171 if (req->type == GETHOSTBYADDR || req->type == GETHOSTBYADDRv6)
1172 {
1173 char buf[INET6_ADDRSTRLEN];
1174
1175 dbg_log ("\t%s (%s)", serv2str[req->type],
1176 inet_ntop (req->type == GETHOSTBYADDR
1177 ? AF_INET : AF_INET6,
1178 key, buf, sizeof (buf)));
1179 }
1180 else
a95a08b4 1181 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
8d8c6efa 1182 }
d67281a7 1183
67479a70 1184 /* Is this service enabled? */
a1ffb40e 1185 if (__glibc_unlikely (!db->enabled))
67479a70 1186 {
ce85d65b 1187 /* No, sent the prepared record. */
2c210d1e
UD
1188 if (TEMP_FAILURE_RETRY (send (fd, db->disabled_iov->iov_base,
1189 db->disabled_iov->iov_len,
1190 MSG_NOSIGNAL))
4c5dd2a2 1191 != (ssize_t) db->disabled_iov->iov_len
23700036 1192 && __builtin_expect (debug_level, 0) > 0)
67479a70
UD
1193 {
1194 /* We have problems sending the result. */
1195 char buf[256];
1196 dbg_log (_("cannot write result: %s"),
1197 strerror_r (errno, buf, sizeof (buf)));
1198 }
d67281a7 1199
67479a70
UD
1200 return;
1201 }
d67281a7 1202
67479a70 1203 /* Be sure we can read the data. */
a1ffb40e 1204 if (__glibc_unlikely (pthread_rwlock_tryrdlock (&db->lock) != 0))
c86e6aec 1205 {
a95a08b4 1206 ++db->head->rdlockdelayed;
c86e6aec
UD
1207 pthread_rwlock_rdlock (&db->lock);
1208 }
67479a70
UD
1209
1210 /* See whether we can handle it from the cache. */
a95a08b4
UD
1211 struct datahead *cached;
1212 cached = (struct datahead *) cache_search (req->type, key, req->key_len,
1213 db, uid);
67479a70
UD
1214 if (cached != NULL)
1215 {
1216 /* Hurray it's in the cache. */
eac10791
UD
1217 ssize_t nwritten;
1218
1219#ifdef HAVE_SENDFILE
a1ffb40e 1220 if (__glibc_likely (db->mmap_used))
eac10791
UD
1221 {
1222 assert (db->wr_fd != -1);
1223 assert ((char *) cached->data > (char *) db->data);
1224 assert ((char *) cached->data - (char *) db->head
1225 + cached->recsize
1226 <= (sizeof (struct database_pers_head)
1227 + db->head->module * sizeof (ref_t)
1228 + db->head->data_size));
bd547139
UD
1229 nwritten = sendfileall (fd, db->wr_fd,
1230 (char *) cached->data
1231 - (char *) db->head, cached->recsize);
eac10791
UD
1232# ifndef __ASSUME_SENDFILE
1233 if (nwritten == -1 && errno == ENOSYS)
1234 goto use_write;
1235# endif
1236 }
1237 else
1238# ifndef __ASSUME_SENDFILE
1239 use_write:
1240# endif
1241#endif
1242 nwritten = writeall (fd, cached->data, cached->recsize);
1243
1244 if (nwritten != cached->recsize
23700036 1245 && __builtin_expect (debug_level, 0) > 0)
67479a70
UD
1246 {
1247 /* We have problems sending the result. */
1248 char buf[256];
1249 dbg_log (_("cannot write result: %s"),
1250 strerror_r (errno, buf, sizeof (buf)));
1251 }
1252
1253 pthread_rwlock_unlock (&db->lock);
1254
1255 return;
1256 }
1257
1258 pthread_rwlock_unlock (&db->lock);
d67281a7 1259 }
23700036 1260 else if (__builtin_expect (debug_level, 0) > 0)
756409c4
UD
1261 {
1262 if (req->type == INVALIDATE)
c207f23b 1263 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
0532e21b 1264 else
a95a08b4 1265 dbg_log ("\t%s", serv2str[req->type]);
756409c4 1266 }
67479a70
UD
1267
1268 /* Handle the request. */
1269 switch (req->type)
d67281a7 1270 {
67479a70 1271 case GETPWBYNAME:
a95a08b4 1272 addpwbyname (db, fd, req, key, uid);
67479a70
UD
1273 break;
1274
1275 case GETPWBYUID:
a95a08b4 1276 addpwbyuid (db, fd, req, key, uid);
67479a70
UD
1277 break;
1278
1279 case GETGRBYNAME:
a95a08b4 1280 addgrbyname (db, fd, req, key, uid);
67479a70
UD
1281 break;
1282
1283 case GETGRBYGID:
a95a08b4 1284 addgrbygid (db, fd, req, key, uid);
67479a70
UD
1285 break;
1286
1287 case GETHOSTBYNAME:
a95a08b4 1288 addhstbyname (db, fd, req, key, uid);
67479a70
UD
1289 break;
1290
1291 case GETHOSTBYNAMEv6:
a95a08b4 1292 addhstbynamev6 (db, fd, req, key, uid);
67479a70
UD
1293 break;
1294
1295 case GETHOSTBYADDR:
a95a08b4 1296 addhstbyaddr (db, fd, req, key, uid);
67479a70
UD
1297 break;
1298
1299 case GETHOSTBYADDRv6:
a95a08b4 1300 addhstbyaddrv6 (db, fd, req, key, uid);
67479a70
UD
1301 break;
1302
d19687d6
UD
1303 case GETAI:
1304 addhstai (db, fd, req, key, uid);
1305 break;
1306
f7e7a396
UD
1307 case INITGROUPS:
1308 addinitgroups (db, fd, req, key, uid);
1309 break;
1310
b21fa963
UD
1311 case GETSERVBYNAME:
1312 addservbyname (db, fd, req, key, uid);
1313 break;
1314
1315 case GETSERVBYPORT:
1316 addservbyport (db, fd, req, key, uid);
1317 break;
1318
684ae515
UD
1319 case GETNETGRENT:
1320 addgetnetgrent (db, fd, req, key, uid);
1321 break;
1322
1323 case INNETGR:
1324 addinnetgr (db, fd, req, key, uid);
1325 break;
1326
67479a70 1327 case GETSTAT:
67479a70 1328 case SHUTDOWN:
756409c4 1329 case INVALIDATE:
70e2ebba
UD
1330 {
1331 /* Get the callers credentials. */
cedc8559 1332#ifdef SO_PEERCRED
70e2ebba
UD
1333 struct ucred caller;
1334 socklen_t optlen = sizeof (caller);
be3c40b6 1335
70e2ebba
UD
1336 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
1337 {
1338 char buf[256];
a1c542bf 1339
c69136ae 1340 dbg_log (_("error getting caller's id: %s"),
70e2ebba
UD
1341 strerror_r (errno, buf, sizeof (buf)));
1342 break;
1343 }
a12ce44f 1344
70e2ebba 1345 uid = caller.uid;
a12ce44f 1346#else
70e2ebba
UD
1347 /* Some systems have no SO_PEERCRED implementation. They don't
1348 care about security so we don't as well. */
1349 uid = 0;
cedc8559 1350#endif
70e2ebba 1351 }
a12ce44f
UD
1352
1353 /* Accept shutdown, getstat and invalidate only from root. For
1354 the stat call also allow the user specified in the config file. */
1355 if (req->type == GETSTAT)
1356 {
1357 if (uid == 0 || uid == stat_uid)
1358 send_stats (fd, dbs);
1359 }
1360 else if (uid == 0)
1361 {
1362 if (req->type == INVALIDATE)
902c4291 1363 invalidate_cache (key, fd);
a12ce44f
UD
1364 else
1365 termination_handler (0);
a1c542bf 1366 }
67479a70
UD
1367 break;
1368
c207f23b
UD
1369 case GETFDPW:
1370 case GETFDGR:
1371 case GETFDHST:
b21fa963 1372 case GETFDSERV:
684ae515 1373 case GETFDNETGR:
c207f23b 1374#ifdef SCM_RIGHTS
000b027e 1375 send_ro_fd (reqinfo[req->type].db, key, fd);
c207f23b
UD
1376#endif
1377 break;
1378
67479a70 1379 default:
64acf8ed
UD
1380 /* Ignore the command, it's nothing we know. */
1381 break;
d67281a7 1382 }
67479a70
UD
1383}
1384
d67281a7 1385
4401d759
UD
1386/* Restart the process. */
1387static void
1388restart (void)
1389{
1390 /* First determine the parameters. We do not use the parameters
1391 passed to main() since in case nscd is started by running the
1392 dynamic linker this will not work. Yes, this is not the usual
1393 case but nscd is part of glibc and we occasionally do this. */
1394 size_t buflen = 1024;
1395 char *buf = alloca (buflen);
1396 size_t readlen = 0;
1397 int fd = open ("/proc/self/cmdline", O_RDONLY);
1398 if (fd == -1)
1399 {
1400 dbg_log (_("\
1401cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
1402 strerror (errno));
1403
1404 paranoia = 0;
1405 return;
1406 }
1407
1408 while (1)
1409 {
1410 ssize_t n = TEMP_FAILURE_RETRY (read (fd, buf + readlen,
1411 buflen - readlen));
1412 if (n == -1)
1413 {
1414 dbg_log (_("\
b21fa963 1415cannot read /proc/self/cmdline: %s; disabling paranoia mode"),
4401d759
UD
1416 strerror (errno));
1417
1418 close (fd);
1419 paranoia = 0;
1420 return;
1421 }
1422
1423 readlen += n;
1424
1425 if (readlen < buflen)
1426 break;
1427
1428 /* We might have to extend the buffer. */
1429 size_t old_buflen = buflen;
1430 char *newp = extend_alloca (buf, buflen, 2 * buflen);
1431 buf = memmove (newp, buf, old_buflen);
1432 }
1433
1434 close (fd);
1435
1436 /* Parse the command line. Worst case scenario: every two
1437 characters form one parameter (one character plus NUL). */
1438 char **argv = alloca ((readlen / 2 + 1) * sizeof (argv[0]));
1439 int argc = 0;
1440
1441 char *cp = buf;
1442 while (cp < buf + readlen)
1443 {
1444 argv[argc++] = cp;
1445 cp = (char *) rawmemchr (cp, '\0') + 1;
1446 }
1447 argv[argc] = NULL;
1448
1449 /* Second, change back to the old user if we changed it. */
1450 if (server_user != NULL)
1451 {
464c9fad 1452 if (setresuid (old_uid, old_uid, old_uid) != 0)
4401d759
UD
1453 {
1454 dbg_log (_("\
1455cannot change to old UID: %s; disabling paranoia mode"),
1456 strerror (errno));
1457
1458 paranoia = 0;
1459 return;
1460 }
1461
464c9fad 1462 if (setresgid (old_gid, old_gid, old_gid) != 0)
4401d759
UD
1463 {
1464 dbg_log (_("\
1465cannot change to old GID: %s; disabling paranoia mode"),
1466 strerror (errno));
1467
8915eace 1468 ignore_value (setuid (server_uid));
4401d759
UD
1469 paranoia = 0;
1470 return;
1471 }
1472 }
1473
1474 /* Next change back to the old working directory. */
1475 if (chdir (oldcwd) == -1)
1476 {
1477 dbg_log (_("\
1478cannot change to old working directory: %s; disabling paranoia mode"),
1479 strerror (errno));
1480
1481 if (server_user != NULL)
1482 {
8915eace
JM
1483 ignore_value (setuid (server_uid));
1484 ignore_value (setgid (server_gid));
4401d759
UD
1485 }
1486 paranoia = 0;
1487 return;
1488 }
1489
1490 /* Synchronize memory. */
528741cb 1491 int32_t certainly[lastdb];
4401d759 1492 for (int cnt = 0; cnt < lastdb; ++cnt)
0fbfe2f7 1493 if (dbs[cnt].enabled)
3e6ce4d7
UD
1494 {
1495 /* Make sure nobody keeps using the database. */
1496 dbs[cnt].head->timestamp = 0;
528741cb
UD
1497 certainly[cnt] = dbs[cnt].head->nscd_certainly_running;
1498 dbs[cnt].head->nscd_certainly_running = 0;
4401d759 1499
3e6ce4d7
UD
1500 if (dbs[cnt].persistent)
1501 // XXX async OK?
1502 msync (dbs[cnt].head, dbs[cnt].memsize, MS_ASYNC);
1503 }
4401d759
UD
1504
1505 /* The preparations are done. */
d9822dbe
UD
1506#ifdef PATH_MAX
1507 char pathbuf[PATH_MAX];
1508#else
1509 char pathbuf[256];
1510#endif
1511 /* Try to exec the real nscd program so the process name (as reported
1512 in /proc/PID/status) will be 'nscd', but fall back to /proc/self/exe
351fe947 1513 if readlink or the exec with the result of the readlink call fails. */
d9822dbe 1514 ssize_t n = readlink ("/proc/self/exe", pathbuf, sizeof (pathbuf) - 1);
351fe947 1515 if (n != -1)
d9822dbe
UD
1516 {
1517 pathbuf[n] = '\0';
1518 execv (pathbuf, argv);
1519 }
351fe947 1520 execv ("/proc/self/exe", argv);
4401d759
UD
1521
1522 /* If we come here, we will never be able to re-exec. */
1523 dbg_log (_("re-exec failed: %s; disabling paranoia mode"),
1524 strerror (errno));
1525
1526 if (server_user != NULL)
1527 {
8915eace
JM
1528 ignore_value (setuid (server_uid));
1529 ignore_value (setgid (server_gid));
4401d759 1530 }
233399bc
UD
1531 if (chdir ("/") != 0)
1532 dbg_log (_("cannot change current working directory to \"/\": %s"),
1533 strerror (errno));
4401d759 1534 paranoia = 0;
528741cb
UD
1535
1536 /* Reenable the databases. */
1537 time_t now = time (NULL);
1538 for (int cnt = 0; cnt < lastdb; ++cnt)
1539 if (dbs[cnt].enabled)
1540 {
1541 dbs[cnt].head->timestamp = now;
1542 dbs[cnt].head->nscd_certainly_running = certainly[cnt];
1543 }
4401d759
UD
1544}
1545
1546
1945c96f
UD
1547/* List of file descriptors. */
1548struct fdlist
1549{
1550 int fd;
1551 struct fdlist *next;
1552};
1553/* Memory allocated for the list. */
1554static struct fdlist *fdlist;
1555/* List of currently ready-to-read file descriptors. */
1556static struct fdlist *readylist;
1557
1558/* Conditional variable and mutex to signal availability of entries in
1559 READYLIST. The condvar is initialized dynamically since we might
1560 use a different clock depending on availability. */
ffb1b882 1561static pthread_cond_t readylist_cond = PTHREAD_COND_INITIALIZER;
1945c96f
UD
1562static pthread_mutex_t readylist_lock = PTHREAD_MUTEX_INITIALIZER;
1563
1564/* The clock to use with the condvar. */
1565static clockid_t timeout_clock = CLOCK_REALTIME;
1566
1567/* Number of threads ready to handle the READYLIST. */
1568static unsigned long int nready;
1569
1570
ffb1b882 1571/* Function for the clean-up threads. */
67479a70
UD
1572static void *
1573__attribute__ ((__noreturn__))
ffb1b882 1574nscd_run_prune (void *p)
67479a70 1575{
1945c96f 1576 const long int my_number = (long int) p;
ffb1b882
UD
1577 assert (dbs[my_number].enabled);
1578
1579 int dont_need_update = setup_thread (&dbs[my_number]);
1580
528741cb
UD
1581 time_t now = time (NULL);
1582
ffb1b882 1583 /* We are running. */
528741cb 1584 dbs[my_number].head->timestamp = now;
ffb1b882 1585
1945c96f 1586 struct timespec prune_ts;
a1ffb40e 1587 if (__glibc_unlikely (clock_gettime (timeout_clock, &prune_ts) == -1))
ffb1b882
UD
1588 /* Should never happen. */
1589 abort ();
1590
1591 /* Compute the initial timeout time. Prevent all the timers to go
1592 off at the same time by adding a db-based value. */
1593 prune_ts.tv_sec += CACHE_PRUNE_INTERVAL + my_number;
528741cb
UD
1594 dbs[my_number].wakeup_time = now + CACHE_PRUNE_INTERVAL + my_number;
1595
1596 pthread_mutex_t *prune_lock = &dbs[my_number].prune_lock;
cd72adeb 1597 pthread_mutex_t *prune_run_lock = &dbs[my_number].prune_run_lock;
528741cb 1598 pthread_cond_t *prune_cond = &dbs[my_number].prune_cond;
264d5b94 1599
528741cb 1600 pthread_mutex_lock (prune_lock);
ffb1b882 1601 while (1)
1945c96f 1602 {
ffb1b882 1603 /* Wait, but not forever. */
5228ba2f
UD
1604 int e = 0;
1605 if (! dbs[my_number].clear_cache)
1606 e = pthread_cond_timedwait (prune_cond, prune_lock, &prune_ts);
528741cb 1607 assert (__builtin_expect (e == 0 || e == ETIMEDOUT, 1));
081fc592 1608
ffb1b882 1609 time_t next_wait;
528741cb 1610 now = time (NULL);
5228ba2f
UD
1611 if (e == ETIMEDOUT || now >= dbs[my_number].wakeup_time
1612 || dbs[my_number].clear_cache)
ffb1b882 1613 {
528741cb
UD
1614 /* We will determine the new timout values based on the
1615 cache content. Should there be concurrent additions to
1616 the cache which are not accounted for in the cache
1617 pruning we want to know about it. Therefore set the
1618 timeout to the maximum. It will be descreased when adding
1619 new entries to the cache, if necessary. */
a4c7ea7b 1620 dbs[my_number].wakeup_time = MAX_TIMEOUT_VALUE;
528741cb 1621
5228ba2f
UD
1622 /* Unconditionally reset the flag. */
1623 time_t prune_now = dbs[my_number].clear_cache ? LONG_MAX : now;
1624 dbs[my_number].clear_cache = 0;
1625
528741cb
UD
1626 pthread_mutex_unlock (prune_lock);
1627
cd72adeb
UD
1628 /* We use a separate lock for running the prune function (instead
1629 of keeping prune_lock locked) because this enables concurrent
1630 invocations of cache_add which might modify the timeout value. */
1631 pthread_mutex_lock (prune_run_lock);
5228ba2f 1632 next_wait = prune_cache (&dbs[my_number], prune_now, -1);
cd72adeb 1633 pthread_mutex_unlock (prune_run_lock);
528741cb 1634
ffb1b882
UD
1635 next_wait = MAX (next_wait, CACHE_PRUNE_INTERVAL);
1636 /* If clients cannot determine for sure whether nscd is running
1637 we need to wake up occasionally to update the timestamp.
1638 Wait 90% of the update period. */
1639#define UPDATE_MAPPING_TIMEOUT (MAPPING_TIMEOUT * 9 / 10)
a1ffb40e 1640 if (__glibc_unlikely (! dont_need_update))
528741cb
UD
1641 {
1642 next_wait = MIN (UPDATE_MAPPING_TIMEOUT, next_wait);
1643 dbs[my_number].head->timestamp = now;
1644 }
1645
1646 pthread_mutex_lock (prune_lock);
ffb1b882
UD
1647
1648 /* Make it known when we will wake up again. */
528741cb
UD
1649 if (now + next_wait < dbs[my_number].wakeup_time)
1650 dbs[my_number].wakeup_time = now + next_wait;
1651 else
1652 next_wait = dbs[my_number].wakeup_time - now;
ffb1b882
UD
1653 }
1654 else
1655 /* The cache was just pruned. Do not do it again now. Just
1656 use the new timeout value. */
1657 next_wait = dbs[my_number].wakeup_time - now;
d67281a7 1658
1945c96f
UD
1659 if (clock_gettime (timeout_clock, &prune_ts) == -1)
1660 /* Should never happen. */
1661 abort ();
0fdb4f42 1662
ffb1b882
UD
1663 /* Compute next timeout time. */
1664 prune_ts.tv_sec += next_wait;
1945c96f 1665 }
ffb1b882
UD
1666}
1667
1668
1669/* This is the main loop. It is replicated in different threads but
ded5b9b7 1670 the use of the ready list makes sure only one thread handles an
ffb1b882
UD
1671 incoming connection. */
1672static void *
1673__attribute__ ((__noreturn__))
1674nscd_run_worker (void *p)
1675{
1676 char buf[256];
1945c96f
UD
1677
1678 /* Initial locking. */
1679 pthread_mutex_lock (&readylist_lock);
1680
1681 /* One more thread available. */
1682 ++nready;
0fdb4f42 1683
1945c96f
UD
1684 while (1)
1685 {
1686 while (readylist == NULL)
ffb1b882 1687 pthread_cond_wait (&readylist_cond, &readylist_lock);
0fdb4f42 1688
1945c96f
UD
1689 struct fdlist *it = readylist->next;
1690 if (readylist->next == readylist)
1691 /* Just one entry on the list. */
1692 readylist = NULL;
1693 else
1694 readylist->next = it->next;
0fdb4f42 1695
1945c96f
UD
1696 /* Extract the information and mark the record ready to be used
1697 again. */
1698 int fd = it->fd;
1699 it->next = NULL;
0fdb4f42 1700
1945c96f
UD
1701 /* One more thread available. */
1702 --nready;
67479a70 1703
1945c96f
UD
1704 /* We are done with the list. */
1705 pthread_mutex_unlock (&readylist_lock);
67479a70 1706
f93fc0b7
UD
1707#ifndef __ASSUME_ACCEPT4
1708 if (have_accept4 < 0)
3ff2c948
UD
1709 {
1710 /* We do not want to block on a short read or so. */
1711 int fl = fcntl (fd, F_GETFL);
1712 if (fl == -1 || fcntl (fd, F_SETFL, fl | O_NONBLOCK) == -1)
1713 goto close_and_out;
1714 }
1715#endif
0fdb4f42
UD
1716
1717 /* Now read the request. */
1945c96f 1718 request_header req;
0fdb4f42
UD
1719 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, &req, sizeof (req)))
1720 != sizeof (req), 0))
d67281a7 1721 {
1945c96f
UD
1722 /* We failed to read data. Note that this also might mean we
1723 failed because we would have blocked. */
0fdb4f42
UD
1724 if (debug_level > 0)
1725 dbg_log (_("short read while reading request: %s"),
1726 strerror_r (errno, buf, sizeof (buf)));
1945c96f 1727 goto close_and_out;
0fdb4f42
UD
1728 }
1729
3c82c131
UD
1730 /* Check whether this is a valid request type. */
1731 if (req.type < GETPWBYNAME || req.type >= LASTREQ)
1732 goto close_and_out;
1733
0fdb4f42
UD
1734 /* Some systems have no SO_PEERCRED implementation. They don't
1735 care about security so we don't as well. */
1945c96f 1736 uid_t uid = -1;
c86e6aec 1737#ifdef SO_PEERCRED
1945c96f
UD
1738 pid_t pid = 0;
1739
a1ffb40e 1740 if (__glibc_unlikely (debug_level > 0))
0fdb4f42
UD
1741 {
1742 struct ucred caller;
1743 socklen_t optlen = sizeof (caller);
c86e6aec 1744
0fdb4f42
UD
1745 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) == 0)
1746 pid = caller.pid;
1747 }
c52137d3
UD
1748#else
1749 const pid_t pid = 0;
cedc8559 1750#endif
a1c542bf 1751
0fdb4f42
UD
1752 /* It should not be possible to crash the nscd with a silly
1753 request (i.e., a terribly large key). We limit the size to 1kb. */
1754 if (__builtin_expect (req.key_len, 1) < 0
1945c96f 1755 || __builtin_expect (req.key_len, 1) > MAXKEYLEN)
0fdb4f42
UD
1756 {
1757 if (debug_level > 0)
1758 dbg_log (_("key length in request too long: %d"), req.key_len);
0fdb4f42
UD
1759 }
1760 else
1761 {
1762 /* Get the key. */
50fd745b 1763 char keybuf[MAXKEYLEN + 1];
0fdb4f42
UD
1764
1765 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, keybuf,
1766 req.key_len))
1767 != req.key_len, 0))
67479a70 1768 {
1945c96f 1769 /* Again, this can also mean we would have blocked. */
98e75a1c 1770 if (debug_level > 0)
0fdb4f42
UD
1771 dbg_log (_("short read while reading request key: %s"),
1772 strerror_r (errno, buf, sizeof (buf)));
1945c96f 1773 goto close_and_out;
67479a70 1774 }
50fd745b 1775 keybuf[req.key_len] = '\0';
0fdb4f42
UD
1776
1777 if (__builtin_expect (debug_level, 0) > 0)
67479a70 1778 {
c86e6aec 1779#ifdef SO_PEERCRED
0fdb4f42
UD
1780 if (pid != 0)
1781 dbg_log (_("\
c86e6aec 1782handle_request: request received (Version = %d) from PID %ld"),
0fdb4f42
UD
1783 req.version, (long int) pid);
1784 else
c86e6aec 1785#endif
0fdb4f42 1786 dbg_log (_("\
c86e6aec 1787handle_request: request received (Version = %d)"), req.version);
0fdb4f42 1788 }
c86e6aec 1789
0fdb4f42 1790 /* Phew, we got all the data, now process it. */
c52137d3 1791 handle_request (fd, &req, keybuf, uid, pid);
d67281a7 1792 }
264d5b94 1793
3c82c131
UD
1794 close_and_out:
1795 /* We are done. */
1796 close (fd);
1797
1945c96f
UD
1798 /* Re-locking. */
1799 pthread_mutex_lock (&readylist_lock);
1800
1801 /* One more thread available. */
1802 ++nready;
1803 }
1ac03a1e 1804 /* NOTREACHED */
1945c96f
UD
1805}
1806
1807
fc03df7a
UD
1808static unsigned int nconns;
1809
1945c96f 1810static void
fc03df7a 1811fd_ready (int fd)
1945c96f 1812{
fc03df7a
UD
1813 pthread_mutex_lock (&readylist_lock);
1814
1815 /* Find an empty entry in FDLIST. */
1816 size_t inner;
1817 for (inner = 0; inner < nconns; ++inner)
1818 if (fdlist[inner].next == NULL)
1819 break;
1820 assert (inner < nconns);
1821
1822 fdlist[inner].fd = fd;
1823
1824 if (readylist == NULL)
1825 readylist = fdlist[inner].next = &fdlist[inner];
1945c96f 1826 else
fc03df7a
UD
1827 {
1828 fdlist[inner].next = readylist->next;
1829 readylist = readylist->next = &fdlist[inner];
1830 }
1831
1832 bool do_signal = true;
a1ffb40e 1833 if (__glibc_unlikely (nready == 0))
fc03df7a
UD
1834 {
1835 ++client_queued;
1836 do_signal = false;
27e82856
UD
1837
1838 /* Try to start another thread to help out. */
1839 pthread_t th;
1840 if (nthreads < max_nthreads
ffb1b882 1841 && pthread_create (&th, &attr, nscd_run_worker,
27e82856
UD
1842 (void *) (long int) nthreads) == 0)
1843 {
1844 /* We got another thread. */
1845 ++nthreads;
908c9e87 1846 /* The new thread might need a kick. */
27e82856
UD
1847 do_signal = true;
1848 }
1849
fc03df7a
UD
1850 }
1851
1852 pthread_mutex_unlock (&readylist_lock);
1853
1854 /* Tell one of the worker threads there is work to do. */
1855 if (do_signal)
1856 pthread_cond_signal (&readylist_cond);
1857}
1945c96f 1858
fc03df7a 1859
4401d759 1860/* Check whether restarting should happen. */
f1d70dad 1861static bool
4401d759
UD
1862restart_p (time_t now)
1863{
1864 return (paranoia && readylist == NULL && nready == nthreads
1865 && now >= restart_time);
1866}
1867
1868
1869/* Array for times a connection was accepted. */
fc03df7a
UD
1870static time_t *starttime;
1871
471514d3
CD
1872#ifdef HAVE_INOTIFY
1873/* Inotify event for changed file. */
1874union __inev
1875{
1876 struct inotify_event i;
1877# ifndef PATH_MAX
1878# define PATH_MAX 1024
1879# endif
1880 char buf[sizeof (struct inotify_event) + PATH_MAX];
1881};
1882
1883/* Process the inotify event in INEV. If the event matches any of the files
1884 registered with a database then mark that database as requiring its cache
1885 to be cleared. We indicate the cache needs clearing by setting
1886 TO_CLEAR[DBCNT] to true for the matching database. */
1887static inline void
1888inotify_check_files (bool *to_clear, union __inev *inev)
1889{
1890 /* Check which of the files changed. */
1891 for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
1892 {
1893 struct traced_file *finfo = dbs[dbcnt].traced_files;
1894
1895 while (finfo != NULL)
1896 {
1897 /* Inotify event watch descriptor matches. */
1898 if (finfo->inotify_descr == inev->i.wd)
1899 {
1900 /* Mark cache as needing to be cleared and reinitialize. */
1901 to_clear[dbcnt] = true;
1902 if (finfo->call_res_init)
1903 res_init ();
1904 return;
1905 }
1906
1907 finfo = finfo->next;
1908 }
1909 }
1910}
1911
1912/* If an entry in the array of booleans TO_CLEAR is TRUE then clear the cache
1913 for the associated database, otherwise do nothing. The TO_CLEAR array must
1914 have LASTDB entries. */
1915static inline void
1916clear_db_cache (bool *to_clear)
1917{
1918 for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
1919 if (to_clear[dbcnt])
1920 {
1921 pthread_mutex_lock (&dbs[dbcnt].prune_lock);
1922 dbs[dbcnt].clear_cache = 1;
1923 pthread_mutex_unlock (&dbs[dbcnt].prune_lock);
1924 pthread_cond_signal (&dbs[dbcnt].prune_cond);
1925 }
1926}
1927
1928#endif
fc03df7a
UD
1929
1930static void
1931__attribute__ ((__noreturn__))
1932main_loop_poll (void)
1933{
1945c96f
UD
1934 struct pollfd *conns = (struct pollfd *) xmalloc (nconns
1935 * sizeof (conns[0]));
1936
1945c96f
UD
1937 conns[0].fd = sock;
1938 conns[0].events = POLLRDNORM;
1939 size_t nused = 1;
1940 size_t firstfree = 1;
1941
5228ba2f
UD
1942#ifdef HAVE_INOTIFY
1943 if (inotify_fd != -1)
1944 {
1945 conns[1].fd = inotify_fd;
1946 conns[1].events = POLLRDNORM;
1947 nused = 2;
1948 firstfree = 2;
1949 }
1950#endif
1951
3a2c0242
UD
1952#ifdef HAVE_NETLINK
1953 size_t idx_nl_status_fd = 0;
1954 if (nl_status_fd != -1)
1955 {
1956 idx_nl_status_fd = nused;
1957 conns[nused].fd = nl_status_fd;
1958 conns[nused].events = POLLRDNORM;
1959 ++nused;
1960 firstfree = nused;
1961 }
1962#endif
1963
1945c96f
UD
1964 while (1)
1965 {
1966 /* Wait for any event. We wait at most a couple of seconds so
1967 that we can check whether we should close any of the accepted
1968 connections since we have not received a request. */
1969#define MAX_ACCEPT_TIMEOUT 30
1970#define MIN_ACCEPT_TIMEOUT 5
1971#define MAIN_THREAD_TIMEOUT \
1972 (MAX_ACCEPT_TIMEOUT * 1000 \
1973 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * 1000 * nused) / (2 * nconns))
1974
1975 int n = poll (conns, nused, MAIN_THREAD_TIMEOUT);
1976
1977 time_t now = time (NULL);
1978
1979 /* If there is a descriptor ready for reading or there is a new
1980 connection, process this now. */
1981 if (n > 0)
67479a70 1982 {
1945c96f
UD
1983 if (conns[0].revents != 0)
1984 {
1985 /* We have a new incoming connection. Accept the connection. */
3ff2c948
UD
1986 int fd;
1987
f93fc0b7 1988#ifndef __ASSUME_ACCEPT4
3ff2c948 1989 fd = -1;
f93fc0b7 1990 if (have_accept4 >= 0)
3ff2c948
UD
1991#endif
1992 {
f93fc0b7 1993 fd = TEMP_FAILURE_RETRY (accept4 (sock, NULL, NULL,
3ff2c948 1994 SOCK_NONBLOCK));
f93fc0b7
UD
1995#ifndef __ASSUME_ACCEPT4
1996 if (have_accept4 == 0)
1997 have_accept4 = fd != -1 || errno != ENOSYS ? 1 : -1;
3ff2c948
UD
1998#endif
1999 }
f93fc0b7
UD
2000#ifndef __ASSUME_ACCEPT4
2001 if (have_accept4 < 0)
3ff2c948
UD
2002 fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
2003#endif
1945c96f 2004
9388dcbb
UD
2005 /* Use the descriptor if we have not reached the limit. */
2006 if (fd >= 0)
1945c96f 2007 {
9388dcbb
UD
2008 if (firstfree < nconns)
2009 {
2010 conns[firstfree].fd = fd;
2011 conns[firstfree].events = POLLRDNORM;
2012 starttime[firstfree] = now;
2013 if (firstfree >= nused)
2014 nused = firstfree + 1;
2015
2016 do
2017 ++firstfree;
2018 while (firstfree < nused && conns[firstfree].fd != -1);
2019 }
2020 else
2021 /* We cannot use the connection so close it. */
2022 close (fd);
1945c96f
UD
2023 }
2024
1945c96f
UD
2025 --n;
2026 }
2027
5228ba2f
UD
2028 size_t first = 1;
2029#ifdef HAVE_INOTIFY
b7432416 2030 if (inotify_fd != -1 && conns[1].fd == inotify_fd)
5228ba2f
UD
2031 {
2032 if (conns[1].revents != 0)
2033 {
b7432416 2034 bool to_clear[lastdb] = { false, };
471514d3 2035 union __inev inev;
5228ba2f 2036
471514d3
CD
2037 /* Read all inotify events for files registered via
2038 register_traced_file(). */
b7432416 2039 while (1)
5228ba2f 2040 {
b7432416
UD
2041 ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev,
2042 sizeof (inev)));
2043 if (nb < (ssize_t) sizeof (struct inotify_event))
2044 {
39e175bb
UD
2045 if (__builtin_expect (nb == -1 && errno != EAGAIN,
2046 0))
b7432416
UD
2047 {
2048 /* Something went wrong when reading the inotify
2049 data. Better disable inotify. */
39e175bb
UD
2050 dbg_log (_("\
2051disabled inotify after read error %d"),
2052 errno);
b7432416
UD
2053 conns[1].fd = -1;
2054 firstfree = 1;
2055 if (nused == 2)
2056 nused = 1;
2057 close (inotify_fd);
2058 inotify_fd = -1;
b7432416
UD
2059 }
2060 break;
2061 }
2062
5228ba2f 2063 /* Check which of the files changed. */
471514d3 2064 inotify_check_files (to_clear, &inev);
5228ba2f
UD
2065 }
2066
b7432416 2067 /* Actually perform the cache clearing. */
471514d3 2068 clear_db_cache (to_clear);
b7432416 2069
5228ba2f
UD
2070 --n;
2071 }
2072
2073 first = 2;
2074 }
2075#endif
2076
3a2c0242
UD
2077#ifdef HAVE_NETLINK
2078 if (idx_nl_status_fd != 0 && conns[idx_nl_status_fd].revents != 0)
2079 {
2080 char buf[4096];
2081 /* Read all the data. We do not interpret it here. */
2082 while (TEMP_FAILURE_RETRY (read (nl_status_fd, buf,
2083 sizeof (buf))) != -1)
2084 ;
2085
2086 dbs[hstdb].head->extra_data[NSCD_HST_IDX_CONF_TIMESTAMP]
2087 = __bump_nl_timestamp ();
2088 }
2089#endif
2090
5228ba2f 2091 for (size_t cnt = first; cnt < nused && n > 0; ++cnt)
1945c96f
UD
2092 if (conns[cnt].revents != 0)
2093 {
fc03df7a 2094 fd_ready (conns[cnt].fd);
1945c96f
UD
2095
2096 /* Clean up the CONNS array. */
2097 conns[cnt].fd = -1;
2098 if (cnt < firstfree)
2099 firstfree = cnt;
2100 if (cnt == nused - 1)
2101 do
2102 --nused;
2103 while (conns[nused - 1].fd == -1);
2104
2105 --n;
2106 }
2107 }
2108
2109 /* Now find entries which have timed out. */
2110 assert (nused > 0);
fc03df7a
UD
2111
2112 /* We make the timeout length depend on the number of file
2113 descriptors currently used. */
1945c96f
UD
2114#define ACCEPT_TIMEOUT \
2115 (MAX_ACCEPT_TIMEOUT \
2116 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * nused) / nconns)
fc03df7a 2117 time_t laststart = now - ACCEPT_TIMEOUT;
1945c96f 2118
fc03df7a
UD
2119 for (size_t cnt = nused - 1; cnt > 0; --cnt)
2120 {
1945c96f
UD
2121 if (conns[cnt].fd != -1 && starttime[cnt] < laststart)
2122 {
2123 /* Remove the entry, it timed out. */
2124 (void) close (conns[cnt].fd);
2125 conns[cnt].fd = -1;
2126
2127 if (cnt < firstfree)
2128 firstfree = cnt;
2129 if (cnt == nused - 1)
2130 do
2131 --nused;
2132 while (conns[nused - 1].fd == -1);
2133 }
67479a70 2134 }
4401d759
UD
2135
2136 if (restart_p (now))
2137 restart ();
67308730 2138 }
d67281a7
UD
2139}
2140
67479a70 2141
fc03df7a
UD
2142#ifdef HAVE_EPOLL
2143static void
2144main_loop_epoll (int efd)
2145{
2146 struct epoll_event ev = { 0, };
2147 int nused = 1;
2148 size_t highest = 0;
2149
2150 /* Add the socket. */
2151 ev.events = EPOLLRDNORM;
2152 ev.data.fd = sock;
2153 if (epoll_ctl (efd, EPOLL_CTL_ADD, sock, &ev) == -1)
2154 /* We cannot use epoll. */
2155 return;
2156
f93fc0b7 2157# ifdef HAVE_INOTIFY
5228ba2f
UD
2158 if (inotify_fd != -1)
2159 {
2160 ev.events = EPOLLRDNORM;
2161 ev.data.fd = inotify_fd;
2162 if (epoll_ctl (efd, EPOLL_CTL_ADD, inotify_fd, &ev) == -1)
2163 /* We cannot use epoll. */
2164 return;
2165 nused = 2;
2166 }
f93fc0b7 2167# endif
5228ba2f 2168
3a2c0242
UD
2169# ifdef HAVE_NETLINK
2170 if (nl_status_fd != -1)
2171 {
2172 ev.events = EPOLLRDNORM;
2173 ev.data.fd = nl_status_fd;
2174 if (epoll_ctl (efd, EPOLL_CTL_ADD, nl_status_fd, &ev) == -1)
2175 /* We cannot use epoll. */
2176 return;
2177 }
2178# endif
2179
fc03df7a
UD
2180 while (1)
2181 {
2182 struct epoll_event revs[100];
2183# define nrevs (sizeof (revs) / sizeof (revs[0]))
2184
2185 int n = epoll_wait (efd, revs, nrevs, MAIN_THREAD_TIMEOUT);
2186
2187 time_t now = time (NULL);
2188
2189 for (int cnt = 0; cnt < n; ++cnt)
2190 if (revs[cnt].data.fd == sock)
2191 {
2192 /* A new connection. */
f93fc0b7
UD
2193 int fd;
2194
2195# ifndef __ASSUME_ACCEPT4
2196 fd = -1;
2197 if (have_accept4 >= 0)
2198# endif
2199 {
2200 fd = TEMP_FAILURE_RETRY (accept4 (sock, NULL, NULL,
2201 SOCK_NONBLOCK));
2202# ifndef __ASSUME_ACCEPT4
2203 if (have_accept4 == 0)
2204 have_accept4 = fd != -1 || errno != ENOSYS ? 1 : -1;
2205# endif
2206 }
2207# ifndef __ASSUME_ACCEPT4
2208 if (have_accept4 < 0)
2209 fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
2210# endif
fc03df7a 2211
f93fc0b7 2212 /* Use the descriptor if we have not reached the limit. */
fc03df7a
UD
2213 if (fd >= 0)
2214 {
2215 /* Try to add the new descriptor. */
2216 ev.data.fd = fd;
2217 if (fd >= nconns
2218 || epoll_ctl (efd, EPOLL_CTL_ADD, fd, &ev) == -1)
2219 /* The descriptor is too large or something went
2220 wrong. Close the descriptor. */
2221 close (fd);
2222 else
2223 {
2224 /* Remember when we accepted the connection. */
2225 starttime[fd] = now;
2226
2227 if (fd > highest)
2228 highest = fd;
2229
2230 ++nused;
2231 }
2232 }
2233 }
f93fc0b7 2234# ifdef HAVE_INOTIFY
5228ba2f
UD
2235 else if (revs[cnt].data.fd == inotify_fd)
2236 {
b7432416 2237 bool to_clear[lastdb] = { false, };
471514d3 2238 union __inev inev;
5228ba2f 2239
471514d3
CD
2240 /* Read all inotify events for files registered via
2241 register_traced_file(). */
b7432416 2242 while (1)
5228ba2f 2243 {
b7432416 2244 ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev,
319b9ad4 2245 sizeof (inev)));
b7432416
UD
2246 if (nb < (ssize_t) sizeof (struct inotify_event))
2247 {
a1ffb40e 2248 if (__glibc_unlikely (nb == -1 && errno != EAGAIN))
b7432416
UD
2249 {
2250 /* Something went wrong when reading the inotify
2251 data. Better disable inotify. */
39e175bb
UD
2252 dbg_log (_("disabled inotify after read error %d"),
2253 errno);
b7432416
UD
2254 (void) epoll_ctl (efd, EPOLL_CTL_DEL, inotify_fd,
2255 NULL);
2256 close (inotify_fd);
2257 inotify_fd = -1;
b7432416
UD
2258 }
2259 break;
2260 }
2261
5228ba2f 2262 /* Check which of the files changed. */
471514d3 2263 inotify_check_files(to_clear, &inev);
5228ba2f 2264 }
b7432416
UD
2265
2266 /* Actually perform the cache clearing. */
471514d3 2267 clear_db_cache (to_clear);
5228ba2f 2268 }
3a2c0242
UD
2269# endif
2270# ifdef HAVE_NETLINK
2271 else if (revs[cnt].data.fd == nl_status_fd)
2272 {
2273 char buf[4096];
2274 /* Read all the data. We do not interpret it here. */
2275 while (TEMP_FAILURE_RETRY (read (nl_status_fd, buf,
2276 sizeof (buf))) != -1)
2277 ;
2278
2279 __bump_nl_timestamp ();
2280 }
f93fc0b7 2281# endif
fc03df7a
UD
2282 else
2283 {
2284 /* Remove the descriptor from the epoll descriptor. */
908c9e87 2285 (void) epoll_ctl (efd, EPOLL_CTL_DEL, revs[cnt].data.fd, NULL);
fc03df7a 2286
2461e3dc 2287 /* Get a worker to handle the request. */
fc03df7a
UD
2288 fd_ready (revs[cnt].data.fd);
2289
2290 /* Reset the time. */
2291 starttime[revs[cnt].data.fd] = 0;
2292 if (revs[cnt].data.fd == highest)
2293 do
2294 --highest;
2295 while (highest > 0 && starttime[highest] == 0);
2296
2297 --nused;
2298 }
2299
2300 /* Now look for descriptors for accepted connections which have
2301 no reply in too long of a time. */
2302 time_t laststart = now - ACCEPT_TIMEOUT;
b7432416
UD
2303 assert (starttime[sock] == 0);
2304 assert (inotify_fd == -1 || starttime[inotify_fd] == 0);
3a2c0242 2305 assert (nl_status_fd == -1 || starttime[nl_status_fd] == 0);
fc03df7a 2306 for (int cnt = highest; cnt > STDERR_FILENO; --cnt)
b7432416 2307 if (starttime[cnt] != 0 && starttime[cnt] < laststart)
fc03df7a
UD
2308 {
2309 /* We are waiting for this one for too long. Close it. */
908c9e87 2310 (void) epoll_ctl (efd, EPOLL_CTL_DEL, cnt, NULL);
fc03df7a
UD
2311
2312 (void) close (cnt);
2313
2314 starttime[cnt] = 0;
2315 if (cnt == highest)
2316 --highest;
2317 }
2318 else if (cnt != sock && starttime[cnt] == 0 && cnt == highest)
2319 --highest;
4401d759
UD
2320
2321 if (restart_p (now))
2322 restart ();
fc03df7a
UD
2323 }
2324}
2325#endif
2326
2327
67479a70 2328/* Start all the threads we want. The initial process is thread no. 1. */
d67281a7 2329void
67479a70 2330start_threads (void)
d67281a7 2331{
1945c96f
UD
2332 /* Initialize the conditional variable we will use. The only
2333 non-standard attribute we might use is the clock selection. */
2334 pthread_condattr_t condattr;
2335 pthread_condattr_init (&condattr);
2336
3078cba2
UD
2337#if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0 \
2338 && defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
1945c96f
UD
2339 /* Determine whether the monotonous clock is available. */
2340 struct timespec dummy;
3078cba2 2341# if _POSIX_MONOTONIC_CLOCK == 0
94d824f9 2342 if (sysconf (_SC_MONOTONIC_CLOCK) > 0)
3078cba2
UD
2343# endif
2344# if _POSIX_CLOCK_SELECTION == 0
94d824f9 2345 if (sysconf (_SC_CLOCK_SELECTION) > 0)
3078cba2 2346# endif
94d824f9
UD
2347 if (clock_getres (CLOCK_MONOTONIC, &dummy) == 0
2348 && pthread_condattr_setclock (&condattr, CLOCK_MONOTONIC) == 0)
2349 timeout_clock = CLOCK_MONOTONIC;
1945c96f 2350#endif
d67281a7 2351
1945c96f
UD
2352 /* Create the attribute for the threads. They are all created
2353 detached. */
67479a70
UD
2354 pthread_attr_init (&attr);
2355 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
27e82856 2356 /* Use 1MB stacks, twice as much for 64-bit architectures. */
7ea8eb02 2357 pthread_attr_setstacksize (&attr, NSCD_THREAD_STACKSIZE);
d67281a7 2358
67479a70
UD
2359 /* We allow less than LASTDB threads only for debugging. */
2360 if (debug_level == 0)
2361 nthreads = MAX (nthreads, lastdb);
d67281a7 2362
ffb1b882
UD
2363 /* Create the threads which prune the databases. */
2364 // XXX Ideally this work would be done by some of the worker threads.
2365 // XXX But this is problematic since we would need to be able to wake
2366 // XXX them up explicitly as well as part of the group handling the
2367 // XXX ready-list. This requires an operation where we can wait on
2368 // XXX two conditional variables at the same time. This operation
2369 // XXX does not exist (yet).
2370 for (long int i = 0; i < lastdb; ++i)
1945c96f 2371 {
ffb1b882
UD
2372 /* Initialize the conditional variable. */
2373 if (pthread_cond_init (&dbs[i].prune_cond, &condattr) != 0)
2374 {
2375 dbg_log (_("could not initialize conditional variable"));
532a6035 2376 do_exit (1, 0, NULL);
ffb1b882
UD
2377 }
2378
1945c96f 2379 pthread_t th;
ffb1b882
UD
2380 if (dbs[i].enabled
2381 && pthread_create (&th, &attr, nscd_run_prune, (void *) i) != 0)
2382 {
2383 dbg_log (_("could not start clean-up thread; terminating"));
532a6035 2384 do_exit (1, 0, NULL);
ffb1b882 2385 }
27e82856 2386 }
ffb1b882
UD
2387
2388 pthread_condattr_destroy (&condattr);
2389
2390 for (long int i = 0; i < nthreads; ++i)
27e82856 2391 {
ffb1b882
UD
2392 pthread_t th;
2393 if (pthread_create (&th, &attr, nscd_run_worker, NULL) != 0)
2394 {
2395 if (i == 0)
2396 {
2397 dbg_log (_("could not start any worker thread; terminating"));
532a6035 2398 do_exit (1, 0, NULL);
ffb1b882
UD
2399 }
2400
2401 break;
2402 }
1945c96f 2403 }
d67281a7 2404
532a6035
SP
2405 /* Now it is safe to let the parent know that we're doing fine and it can
2406 exit. */
2407 notify_parent (0);
2408
fc03df7a
UD
2409 /* Determine how much room for descriptors we should initially
2410 allocate. This might need to change later if we cap the number
2411 with MAXCONN. */
2412 const long int nfds = sysconf (_SC_OPEN_MAX);
2413#define MINCONN 32
2414#define MAXCONN 16384
2415 if (nfds == -1 || nfds > MAXCONN)
2416 nconns = MAXCONN;
2417 else if (nfds < MINCONN)
2418 nconns = MINCONN;
2419 else
2420 nconns = nfds;
2421
2422 /* We need memory to pass descriptors on to the worker threads. */
2423 fdlist = (struct fdlist *) xcalloc (nconns, sizeof (fdlist[0]));
2424 /* Array to keep track when connection was accepted. */
2425 starttime = (time_t *) xcalloc (nconns, sizeof (starttime[0]));
2426
1945c96f
UD
2427 /* In the main thread we execute the loop which handles incoming
2428 connections. */
fc03df7a
UD
2429#ifdef HAVE_EPOLL
2430 int efd = epoll_create (100);
2431 if (efd != -1)
2432 {
2433 main_loop_epoll (efd);
2434 close (efd);
2435 }
2436#endif
2437
2438 main_loop_poll ();
d67281a7 2439}
057685e4
UD
2440
2441
2442/* Look up the uid, gid, and supplementary groups to run nscd as. When
2443 this function is called, we are not listening on the nscd socket yet so
2444 we can just use the ordinary lookup functions without causing a lockup */
2445static void
2446begin_drop_privileges (void)
2447{
a95a08b4 2448 struct passwd *pwd = getpwnam (server_user);
057685e4
UD
2449
2450 if (pwd == NULL)
2451 {
2452 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
532a6035
SP
2453 do_exit (EXIT_FAILURE, 0,
2454 _("Failed to run nscd as user '%s'"), server_user);
057685e4
UD
2455 }
2456
2457 server_uid = pwd->pw_uid;
2458 server_gid = pwd->pw_gid;
2459
4401d759
UD
2460 /* Save the old UID/GID if we have to change back. */
2461 if (paranoia)
2462 {
2463 old_uid = getuid ();
2464 old_gid = getgid ();
2465 }
2466
a95a08b4
UD
2467 if (getgrouplist (server_user, server_gid, NULL, &server_ngroups) == 0)
2468 {
2469 /* This really must never happen. */
2470 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
532a6035
SP
2471 do_exit (EXIT_FAILURE, errno,
2472 _("initial getgrouplist failed"));
a95a08b4 2473 }
057685e4 2474
a95a08b4 2475 server_groups = (gid_t *) xmalloc (server_ngroups * sizeof (gid_t));
057685e4
UD
2476
2477 if (getgrouplist (server_user, server_gid, server_groups, &server_ngroups)
2478 == -1)
2479 {
2480 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
532a6035 2481 do_exit (EXIT_FAILURE, errno, _("getgrouplist failed"));
057685e4
UD
2482 }
2483}
2484
2485
2486/* Call setgroups(), setgid(), and setuid() to drop root privileges and
2487 run nscd as the user specified in the configuration file. */
2488static void
2489finish_drop_privileges (void)
2490{
1f063dca
UD
2491#if defined HAVE_LIBAUDIT && defined HAVE_LIBCAP
2492 /* We need to preserve the capabilities to connect to the audit daemon. */
2493 cap_t new_caps = preserve_capabilities ();
2494#endif
2495
057685e4
UD
2496 if (setgroups (server_ngroups, server_groups) == -1)
2497 {
2498 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
532a6035 2499 do_exit (EXIT_FAILURE, errno, _("setgroups failed"));
057685e4
UD
2500 }
2501
91287339
UD
2502 int res;
2503 if (paranoia)
2504 res = setresgid (server_gid, server_gid, old_gid);
2505 else
2506 res = setgid (server_gid);
2507 if (res == -1)
057685e4
UD
2508 {
2509 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
532a6035 2510 do_exit (4, errno, "setgid");
057685e4
UD
2511 }
2512
91287339
UD
2513 if (paranoia)
2514 res = setresuid (server_uid, server_uid, old_uid);
2515 else
2516 res = setuid (server_uid);
2517 if (res == -1)
057685e4
UD
2518 {
2519 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
532a6035 2520 do_exit (4, errno, "setuid");
057685e4 2521 }
1f063dca
UD
2522
2523#if defined HAVE_LIBAUDIT && defined HAVE_LIBCAP
2524 /* Remove the temporary capabilities. */
2525 install_real_capabilities (new_caps);
2526#endif
057685e4 2527}