Updated to fedora-glibc-20090102T2110
[glibc.git] / nscd / connections.c
blobdd934c1106de44294fa963bc85be47f98f4db0ec
1 /* Inner loops of cache daemon.
2 Copyright (C) 1998-2007, 2008 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
6 This program is free software; you can redistribute it and/or modify
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.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20 #include <alloca.h>
21 #include <assert.h>
22 #include <atomic.h>
23 #include <error.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <grp.h>
27 #include <libintl.h>
28 #include <pthread.h>
29 #include <pwd.h>
30 #include <resolv.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <arpa/inet.h>
35 #ifdef HAVE_EPOLL
36 # include <sys/epoll.h>
37 #endif
38 #ifdef HAVE_INOTIFY
39 # include <sys/inotify.h>
40 #endif
41 #include <sys/mman.h>
42 #include <sys/param.h>
43 #include <sys/poll.h>
44 #ifdef HAVE_SENDFILE
45 # include <sys/sendfile.h>
46 #endif
47 #include <sys/socket.h>
48 #include <sys/stat.h>
49 #include <sys/un.h>
51 #include "nscd.h"
52 #include "dbg_log.h"
53 #include "selinux.h"
54 #include <resolv/resolv.h>
55 #ifdef HAVE_SENDFILE
56 # include <kernel-features.h>
57 #endif
60 /* Wrapper functions with error checking for standard functions. */
61 extern void *xmalloc (size_t n);
62 extern void *xcalloc (size_t n, size_t s);
63 extern void *xrealloc (void *o, size_t n);
65 /* Support to run nscd as an unprivileged user */
66 const char *server_user;
67 static uid_t server_uid;
68 static gid_t server_gid;
69 const char *stat_user;
70 uid_t stat_uid;
71 static gid_t *server_groups;
72 #ifndef NGROUPS
73 # define NGROUPS 32
74 #endif
75 static int server_ngroups;
77 static pthread_attr_t attr;
79 static void begin_drop_privileges (void);
80 static void finish_drop_privileges (void);
82 /* Map request type to a string. */
83 const char *const serv2str[LASTREQ] =
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",
94 [GETSTAT] = "GETSTAT",
95 [INVALIDATE] = "INVALIDATE",
96 [GETFDPW] = "GETFDPW",
97 [GETFDGR] = "GETFDGR",
98 [GETFDHST] = "GETFDHST",
99 [GETAI] = "GETAI",
100 [INITGROUPS] = "INITGROUPS",
101 [GETSERVBYNAME] = "GETSERVBYNAME",
102 [GETSERVBYPORT] = "GETSERVBYPORT",
103 [GETFDSERV] = "GETFDSERV"
106 /* The control data structures for the services. */
107 struct database_dyn dbs[lastdb] =
109 [pwddb] = {
110 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
111 .prune_lock = PTHREAD_MUTEX_INITIALIZER,
112 .prune_run_lock = PTHREAD_MUTEX_INITIALIZER,
113 .enabled = 0,
114 .check_file = 1,
115 .persistent = 0,
116 .propagate = 1,
117 .shared = 0,
118 .max_db_size = DEFAULT_MAX_DB_SIZE,
119 .suggested_module = DEFAULT_SUGGESTED_MODULE,
120 .reset_res = 0,
121 .filename = "/etc/passwd",
122 .db_filename = _PATH_NSCD_PASSWD_DB,
123 .disabled_iov = &pwd_iov_disabled,
124 .postimeout = 3600,
125 .negtimeout = 20,
126 .wr_fd = -1,
127 .ro_fd = -1,
128 .mmap_used = false
130 [grpdb] = {
131 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
132 .prune_lock = PTHREAD_MUTEX_INITIALIZER,
133 .prune_run_lock = PTHREAD_MUTEX_INITIALIZER,
134 .enabled = 0,
135 .check_file = 1,
136 .persistent = 0,
137 .propagate = 1,
138 .shared = 0,
139 .max_db_size = DEFAULT_MAX_DB_SIZE,
140 .suggested_module = DEFAULT_SUGGESTED_MODULE,
141 .reset_res = 0,
142 .filename = "/etc/group",
143 .db_filename = _PATH_NSCD_GROUP_DB,
144 .disabled_iov = &grp_iov_disabled,
145 .postimeout = 3600,
146 .negtimeout = 60,
147 .wr_fd = -1,
148 .ro_fd = -1,
149 .mmap_used = false
151 [hstdb] = {
152 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
153 .prune_lock = PTHREAD_MUTEX_INITIALIZER,
154 .prune_run_lock = PTHREAD_MUTEX_INITIALIZER,
155 .enabled = 0,
156 .check_file = 1,
157 .persistent = 0,
158 .propagate = 0, /* Not used. */
159 .shared = 0,
160 .max_db_size = DEFAULT_MAX_DB_SIZE,
161 .suggested_module = DEFAULT_SUGGESTED_MODULE,
162 .reset_res = 1,
163 .filename = "/etc/hosts",
164 .db_filename = _PATH_NSCD_HOSTS_DB,
165 .disabled_iov = &hst_iov_disabled,
166 .postimeout = 3600,
167 .negtimeout = 20,
168 .wr_fd = -1,
169 .ro_fd = -1,
170 .mmap_used = false
172 [servdb] = {
173 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
174 .prune_lock = PTHREAD_MUTEX_INITIALIZER,
175 .prune_run_lock = PTHREAD_MUTEX_INITIALIZER,
176 .enabled = 0,
177 .check_file = 1,
178 .persistent = 0,
179 .propagate = 0, /* Not used. */
180 .shared = 0,
181 .max_db_size = DEFAULT_MAX_DB_SIZE,
182 .suggested_module = DEFAULT_SUGGESTED_MODULE,
183 .reset_res = 0,
184 .filename = "/etc/services",
185 .db_filename = _PATH_NSCD_SERVICES_DB,
186 .disabled_iov = &serv_iov_disabled,
187 .postimeout = 28800,
188 .negtimeout = 20,
189 .wr_fd = -1,
190 .ro_fd = -1,
191 .mmap_used = false
196 /* Mapping of request type to database. */
197 static struct
199 bool data_request;
200 struct database_dyn *db;
201 } const reqinfo[LASTREQ] =
203 [GETPWBYNAME] = { true, &dbs[pwddb] },
204 [GETPWBYUID] = { true, &dbs[pwddb] },
205 [GETGRBYNAME] = { true, &dbs[grpdb] },
206 [GETGRBYGID] = { true, &dbs[grpdb] },
207 [GETHOSTBYNAME] = { true, &dbs[hstdb] },
208 [GETHOSTBYNAMEv6] = { true, &dbs[hstdb] },
209 [GETHOSTBYADDR] = { true, &dbs[hstdb] },
210 [GETHOSTBYADDRv6] = { true, &dbs[hstdb] },
211 [SHUTDOWN] = { false, NULL },
212 [GETSTAT] = { false, NULL },
213 [SHUTDOWN] = { false, NULL },
214 [GETFDPW] = { false, &dbs[pwddb] },
215 [GETFDGR] = { false, &dbs[grpdb] },
216 [GETFDHST] = { false, &dbs[hstdb] },
217 [GETAI] = { true, &dbs[hstdb] },
218 [INITGROUPS] = { true, &dbs[grpdb] },
219 [GETSERVBYNAME] = { true, &dbs[servdb] },
220 [GETSERVBYPORT] = { true, &dbs[servdb] },
221 [GETFDSERV] = { false, &dbs[servdb] }
225 /* Initial number of threads to use. */
226 int nthreads = -1;
227 /* Maximum number of threads to use. */
228 int max_nthreads = 32;
230 /* Socket for incoming connections. */
231 static int sock;
233 #ifdef HAVE_INOTIFY
234 /* Inotify descriptor. */
235 static int inotify_fd = -1;
237 /* Watch descriptor for resolver configuration file. */
238 static int resolv_conf_descr = -1;
239 #endif
241 #ifndef __ASSUME_SOCK_CLOEXEC
242 /* Negative if SOCK_CLOEXEC is not supported, positive if it is, zero
243 before be know the result. */
244 static int have_sock_cloexec;
245 #endif
246 #ifndef __ASSUME_ACCEPT4
247 static int have_accept4;
248 #endif
250 /* Number of times clients had to wait. */
251 unsigned long int client_queued;
253 /* Data structure for recording in-flight memory allocation. */
254 __thread struct mem_in_flight mem_in_flight attribute_tls_model_ie;
255 /* Global list of the mem_in_flight variables of all the threads. */
256 struct mem_in_flight *mem_in_flight_list;
259 ssize_t
260 writeall (int fd, const void *buf, size_t len)
262 size_t n = len;
263 ssize_t ret;
266 ret = TEMP_FAILURE_RETRY (send (fd, buf, n, MSG_NOSIGNAL));
267 if (ret <= 0)
268 break;
269 buf = (const char *) buf + ret;
270 n -= ret;
272 while (n > 0);
273 return ret < 0 ? ret : len - n;
277 #ifdef HAVE_SENDFILE
278 ssize_t
279 sendfileall (int tofd, int fromfd, off_t off, size_t len)
281 ssize_t n = len;
282 ssize_t ret;
286 ret = TEMP_FAILURE_RETRY (sendfile (tofd, fromfd, &off, n));
287 if (ret <= 0)
288 break;
289 n -= ret;
291 while (n > 0);
292 return ret < 0 ? ret : len - n;
294 #endif
297 enum usekey
299 use_not = 0,
300 /* The following three are not really used, they are symbolic constants. */
301 use_first = 16,
302 use_begin = 32,
303 use_end = 64,
305 use_he = 1,
306 use_he_begin = use_he | use_begin,
307 use_he_end = use_he | use_end,
308 #if SEPARATE_KEY
309 use_key = 2,
310 use_key_begin = use_key | use_begin,
311 use_key_end = use_key | use_end,
312 use_key_first = use_key_begin | use_first,
313 #endif
314 use_data = 3,
315 use_data_begin = use_data | use_begin,
316 use_data_end = use_data | use_end,
317 use_data_first = use_data_begin | use_first
321 static int
322 check_use (const char *data, nscd_ssize_t first_free, uint8_t *usemap,
323 enum usekey use, ref_t start, size_t len)
325 assert (len >= 2);
327 if (start > first_free || start + len > first_free
328 || (start & BLOCK_ALIGN_M1))
329 return 0;
331 if (usemap[start] == use_not)
333 /* Add the start marker. */
334 usemap[start] = use | use_begin;
335 use &= ~use_first;
337 while (--len > 0)
338 if (usemap[++start] != use_not)
339 return 0;
340 else
341 usemap[start] = use;
343 /* Add the end marker. */
344 usemap[start] = use | use_end;
346 else if ((usemap[start] & ~use_first) == ((use | use_begin) & ~use_first))
348 /* Hash entries can't be shared. */
349 if (use == use_he)
350 return 0;
352 usemap[start] |= (use & use_first);
353 use &= ~use_first;
355 while (--len > 1)
356 if (usemap[++start] != use)
357 return 0;
359 if (usemap[++start] != (use | use_end))
360 return 0;
362 else
363 /* Points to a wrong object or somewhere in the middle. */
364 return 0;
366 return 1;
370 /* Verify data in persistent database. */
371 static int
372 verify_persistent_db (void *mem, struct database_pers_head *readhead, int dbnr)
374 assert (dbnr == pwddb || dbnr == grpdb || dbnr == hstdb || dbnr == servdb);
376 time_t now = time (NULL);
378 struct database_pers_head *head = mem;
379 struct database_pers_head head_copy = *head;
381 /* Check that the header that was read matches the head in the database. */
382 if (memcmp (head, readhead, sizeof (*head)) != 0)
383 return 0;
385 /* First some easy tests: make sure the database header is sane. */
386 if (head->version != DB_VERSION
387 || head->header_size != sizeof (*head)
388 /* We allow a timestamp to be one hour ahead of the current time.
389 This should cover daylight saving time changes. */
390 || head->timestamp > now + 60 * 60 + 60
391 || (head->gc_cycle & 1)
392 || head->module == 0
393 || (size_t) head->module > INT32_MAX / sizeof (ref_t)
394 || (size_t) head->data_size > INT32_MAX - head->module * sizeof (ref_t)
395 || head->first_free < 0
396 || head->first_free > head->data_size
397 || (head->first_free & BLOCK_ALIGN_M1) != 0
398 || head->maxnentries < 0
399 || head->maxnsearched < 0)
400 return 0;
402 uint8_t *usemap = calloc (head->first_free, 1);
403 if (usemap == NULL)
404 return 0;
406 const char *data = (char *) &head->array[roundup (head->module,
407 ALIGN / sizeof (ref_t))];
409 nscd_ssize_t he_cnt = 0;
410 for (nscd_ssize_t cnt = 0; cnt < head->module; ++cnt)
412 ref_t trail = head->array[cnt];
413 ref_t work = trail;
414 int tick = 0;
416 while (work != ENDREF)
418 if (! check_use (data, head->first_free, usemap, use_he, work,
419 sizeof (struct hashentry)))
420 goto fail;
422 /* Now we know we can dereference the record. */
423 struct hashentry *here = (struct hashentry *) (data + work);
425 ++he_cnt;
427 /* Make sure the record is for this type of service. */
428 if (here->type >= LASTREQ
429 || reqinfo[here->type].db != &dbs[dbnr])
430 goto fail;
432 /* Validate boolean field value. */
433 if (here->first != false && here->first != true)
434 goto fail;
436 if (here->len < 0)
437 goto fail;
439 /* Now the data. */
440 if (here->packet < 0
441 || here->packet > head->first_free
442 || here->packet + sizeof (struct datahead) > head->first_free)
443 goto fail;
445 struct datahead *dh = (struct datahead *) (data + here->packet);
447 if (! check_use (data, head->first_free, usemap,
448 use_data | (here->first ? use_first : 0),
449 here->packet, dh->allocsize))
450 goto fail;
452 if (dh->allocsize < sizeof (struct datahead)
453 || dh->recsize > dh->allocsize
454 || (dh->notfound != false && dh->notfound != true)
455 || (dh->usable != false && dh->usable != true))
456 goto fail;
458 if (here->key < here->packet + sizeof (struct datahead)
459 || here->key > here->packet + dh->allocsize
460 || here->key + here->len > here->packet + dh->allocsize)
462 #if SEPARATE_KEY
463 /* If keys can appear outside of data, this should be done
464 instead. But gc doesn't mark the data in that case. */
465 if (! check_use (data, head->first_free, usemap,
466 use_key | (here->first ? use_first : 0),
467 here->key, here->len))
468 #endif
469 goto fail;
472 work = here->next;
474 if (work == trail)
475 /* A circular list, this must not happen. */
476 goto fail;
477 if (tick)
478 trail = ((struct hashentry *) (data + trail))->next;
479 tick = 1 - tick;
483 if (he_cnt != head->nentries)
484 goto fail;
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)
490 #if SEPARATE_KEY
491 if (usemap[idx] == use_key_begin)
492 goto fail;
493 #endif
494 if (usemap[idx] == use_data_begin)
495 goto fail;
498 /* Finally, make sure the database hasn't changed since the first test. */
499 if (memcmp (mem, &head_copy, sizeof (*head)) != 0)
500 goto fail;
502 free (usemap);
503 return 1;
505 fail:
506 free (usemap);
507 return 0;
511 #ifdef O_CLOEXEC
512 # define EXTRA_O_FLAGS O_CLOEXEC
513 #else
514 # define EXTRA_O_FLAGS 0
515 #endif
518 /* Initialize database information structures. */
519 void
520 nscd_init (void)
522 /* Look up unprivileged uid/gid/groups before we start listening on the
523 socket */
524 if (server_user != NULL)
525 begin_drop_privileges ();
527 if (nthreads == -1)
528 /* No configuration for this value, assume a default. */
529 nthreads = 4;
531 #ifdef HAVE_INOTIFY
532 /* Use inotify to recognize changed files. */
533 inotify_fd = inotify_init1 (IN_NONBLOCK);
534 # ifndef __ASSUME_IN_NONBLOCK
535 if (inotify_fd == -1 && errno == ENOSYS)
537 inotify_fd = inotify_init ();
538 if (inotify_fd != -1)
539 fcntl (inotify_fd, F_SETFL, O_RDONLY | O_NONBLOCK);
541 # endif
542 #endif
544 for (size_t cnt = 0; cnt < lastdb; ++cnt)
545 if (dbs[cnt].enabled)
547 pthread_rwlock_init (&dbs[cnt].lock, NULL);
548 pthread_mutex_init (&dbs[cnt].memlock, NULL);
550 if (dbs[cnt].persistent)
552 /* Try to open the appropriate file on disk. */
553 int fd = open (dbs[cnt].db_filename, O_RDWR | EXTRA_O_FLAGS);
554 if (fd != -1)
556 char *msg = NULL;
557 struct stat64 st;
558 void *mem;
559 size_t total;
560 struct database_pers_head head;
561 ssize_t n = TEMP_FAILURE_RETRY (read (fd, &head,
562 sizeof (head)));
563 if (n != sizeof (head) || fstat64 (fd, &st) != 0)
565 fail_db_errno:
566 /* The code is single-threaded at this point so
567 using strerror is just fine. */
568 msg = strerror (errno);
569 fail_db:
570 dbg_log (_("invalid persistent database file \"%s\": %s"),
571 dbs[cnt].db_filename, msg);
572 unlink (dbs[cnt].db_filename);
574 else if (head.module == 0 && head.data_size == 0)
576 /* The file has been created, but the head has not
577 been initialized yet. */
578 msg = _("uninitialized header");
579 goto fail_db;
581 else if (head.header_size != (int) sizeof (head))
583 msg = _("header size does not match");
584 goto fail_db;
586 else if ((total = (sizeof (head)
587 + roundup (head.module * sizeof (ref_t),
588 ALIGN)
589 + head.data_size))
590 > st.st_size
591 || total < sizeof (head))
593 msg = _("file size does not match");
594 goto fail_db;
596 /* Note we map with the maximum size allowed for the
597 database. This is likely much larger than the
598 actual file size. This is OK on most OSes since
599 extensions of the underlying file will
600 automatically translate more pages available for
601 memory access. */
602 else if ((mem = mmap (NULL, dbs[cnt].max_db_size,
603 PROT_READ | PROT_WRITE,
604 MAP_SHARED, fd, 0))
605 == MAP_FAILED)
606 goto fail_db_errno;
607 else if (!verify_persistent_db (mem, &head, cnt))
609 munmap (mem, total);
610 msg = _("verification failed");
611 goto fail_db;
613 else
615 /* Success. We have the database. */
616 dbs[cnt].head = mem;
617 dbs[cnt].memsize = total;
618 dbs[cnt].data = (char *)
619 &dbs[cnt].head->array[roundup (dbs[cnt].head->module,
620 ALIGN / sizeof (ref_t))];
621 dbs[cnt].mmap_used = true;
623 if (dbs[cnt].suggested_module > head.module)
624 dbg_log (_("suggested size of table for database %s larger than the persistent database's table"),
625 dbnames[cnt]);
627 dbs[cnt].wr_fd = fd;
628 fd = -1;
629 /* We also need a read-only descriptor. */
630 if (dbs[cnt].shared)
632 dbs[cnt].ro_fd = open (dbs[cnt].db_filename,
633 O_RDONLY | EXTRA_O_FLAGS);
634 if (dbs[cnt].ro_fd == -1)
635 dbg_log (_("\
636 cannot create read-only descriptor for \"%s\"; no mmap"),
637 dbs[cnt].db_filename);
640 // XXX Shall we test whether the descriptors actually
641 // XXX point to the same file?
644 /* Close the file descriptors in case something went
645 wrong in which case the variable have not been
646 assigned -1. */
647 if (fd != -1)
648 close (fd);
652 if (dbs[cnt].head == NULL)
654 /* No database loaded. Allocate the data structure,
655 possibly on disk. */
656 struct database_pers_head head;
657 size_t total = (sizeof (head)
658 + roundup (dbs[cnt].suggested_module
659 * sizeof (ref_t), ALIGN)
660 + (dbs[cnt].suggested_module
661 * DEFAULT_DATASIZE_PER_BUCKET));
663 /* Try to create the database. If we do not need a
664 persistent database create a temporary file. */
665 int fd;
666 int ro_fd = -1;
667 if (dbs[cnt].persistent)
669 fd = open (dbs[cnt].db_filename,
670 O_RDWR | O_CREAT | O_EXCL | O_TRUNC | EXTRA_O_FLAGS,
671 S_IRUSR | S_IWUSR);
672 if (fd != -1 && dbs[cnt].shared)
673 ro_fd = open (dbs[cnt].db_filename,
674 O_RDONLY | EXTRA_O_FLAGS);
676 else
678 char fname[] = _PATH_NSCD_XYZ_DB_TMP;
679 fd = mkostemp (fname, EXTRA_O_FLAGS);
681 /* We do not need the file name anymore after we
682 opened another file descriptor in read-only mode. */
683 if (fd != -1)
685 if (dbs[cnt].shared)
686 ro_fd = open (fname, O_RDONLY | EXTRA_O_FLAGS);
688 unlink (fname);
692 if (fd == -1)
694 if (errno == EEXIST)
696 dbg_log (_("database for %s corrupted or simultaneously used; remove %s manually if necessary and restart"),
697 dbnames[cnt], dbs[cnt].db_filename);
698 // XXX Correct way to terminate?
699 exit (1);
702 if (dbs[cnt].persistent)
703 dbg_log (_("cannot create %s; no persistent database used"),
704 dbs[cnt].db_filename);
705 else
706 dbg_log (_("cannot create %s; no sharing possible"),
707 dbs[cnt].db_filename);
709 dbs[cnt].persistent = 0;
710 // XXX remember: no mmap
712 else
714 /* Tell the user if we could not create the read-only
715 descriptor. */
716 if (ro_fd == -1 && dbs[cnt].shared)
717 dbg_log (_("\
718 cannot create read-only descriptor for \"%s\"; no mmap"),
719 dbs[cnt].db_filename);
721 /* Before we create the header, initialiye the hash
722 table. So that if we get interrupted if writing
723 the header we can recognize a partially initialized
724 database. */
725 size_t ps = sysconf (_SC_PAGESIZE);
726 char tmpbuf[ps];
727 assert (~ENDREF == 0);
728 memset (tmpbuf, '\xff', ps);
730 size_t remaining = dbs[cnt].suggested_module * sizeof (ref_t);
731 off_t offset = sizeof (head);
733 size_t towrite;
734 if (offset % ps != 0)
736 towrite = MIN (remaining, ps - (offset % ps));
737 if (pwrite (fd, tmpbuf, towrite, offset) != towrite)
738 goto write_fail;
739 offset += towrite;
740 remaining -= towrite;
743 while (remaining > ps)
745 if (pwrite (fd, tmpbuf, ps, offset) == -1)
746 goto write_fail;
747 offset += ps;
748 remaining -= ps;
751 if (remaining > 0
752 && pwrite (fd, tmpbuf, remaining, offset) != remaining)
753 goto write_fail;
755 /* Create the header of the file. */
756 struct database_pers_head head =
758 .version = DB_VERSION,
759 .header_size = sizeof (head),
760 .module = dbs[cnt].suggested_module,
761 .data_size = (dbs[cnt].suggested_module
762 * DEFAULT_DATASIZE_PER_BUCKET),
763 .first_free = 0
765 void *mem;
767 if ((TEMP_FAILURE_RETRY (write (fd, &head, sizeof (head)))
768 != sizeof (head))
769 || (TEMP_FAILURE_RETRY_VAL (posix_fallocate (fd, 0, total))
770 != 0)
771 || (mem = mmap (NULL, dbs[cnt].max_db_size,
772 PROT_READ | PROT_WRITE,
773 MAP_SHARED, fd, 0)) == MAP_FAILED)
775 write_fail:
776 unlink (dbs[cnt].db_filename);
777 dbg_log (_("cannot write to database file %s: %s"),
778 dbs[cnt].db_filename, strerror (errno));
779 dbs[cnt].persistent = 0;
781 else
783 /* Success. */
784 dbs[cnt].head = mem;
785 dbs[cnt].data = (char *)
786 &dbs[cnt].head->array[roundup (dbs[cnt].head->module,
787 ALIGN / sizeof (ref_t))];
788 dbs[cnt].memsize = total;
789 dbs[cnt].mmap_used = true;
791 /* Remember the descriptors. */
792 dbs[cnt].wr_fd = fd;
793 dbs[cnt].ro_fd = ro_fd;
794 fd = -1;
795 ro_fd = -1;
798 if (fd != -1)
799 close (fd);
800 if (ro_fd != -1)
801 close (ro_fd);
805 #if !defined O_CLOEXEC || !defined __ASSUME_O_CLOEXEC
806 /* We do not check here whether the O_CLOEXEC provided to the
807 open call was successful or not. The two fcntl calls are
808 only performed once each per process start-up and therefore
809 is not noticeable at all. */
810 if (paranoia
811 && ((dbs[cnt].wr_fd != -1
812 && fcntl (dbs[cnt].wr_fd, F_SETFD, FD_CLOEXEC) == -1)
813 || (dbs[cnt].ro_fd != -1
814 && fcntl (dbs[cnt].ro_fd, F_SETFD, FD_CLOEXEC) == -1)))
816 dbg_log (_("\
817 cannot set socket to close on exec: %s; disabling paranoia mode"),
818 strerror (errno));
819 paranoia = 0;
821 #endif
823 if (dbs[cnt].head == NULL)
825 /* We do not use the persistent database. Just
826 create an in-memory data structure. */
827 assert (! dbs[cnt].persistent);
829 dbs[cnt].head = xmalloc (sizeof (struct database_pers_head)
830 + (dbs[cnt].suggested_module
831 * sizeof (ref_t)));
832 memset (dbs[cnt].head, '\0', sizeof (struct database_pers_head));
833 assert (~ENDREF == 0);
834 memset (dbs[cnt].head->array, '\xff',
835 dbs[cnt].suggested_module * sizeof (ref_t));
836 dbs[cnt].head->module = dbs[cnt].suggested_module;
837 dbs[cnt].head->data_size = (DEFAULT_DATASIZE_PER_BUCKET
838 * dbs[cnt].head->module);
839 dbs[cnt].data = xmalloc (dbs[cnt].head->data_size);
840 dbs[cnt].head->first_free = 0;
842 dbs[cnt].shared = 0;
843 assert (dbs[cnt].ro_fd == -1);
846 dbs[cnt].inotify_descr = -1;
847 if (dbs[cnt].check_file)
849 #ifdef HAVE_INOTIFY
850 if (inotify_fd < 0
851 || (dbs[cnt].inotify_descr
852 = inotify_add_watch (inotify_fd, dbs[cnt].filename,
853 IN_DELETE_SELF | IN_MODIFY)) < 0)
854 /* We cannot notice changes in the main thread. */
855 #endif
857 /* We need the modification date of the file. */
858 struct stat64 st;
860 if (stat64 (dbs[cnt].filename, &st) < 0)
862 /* We cannot stat() the file, disable file checking. */
863 dbg_log (_("cannot stat() file `%s': %s"),
864 dbs[cnt].filename, strerror (errno));
865 dbs[cnt].check_file = 0;
867 else
868 dbs[cnt].file_mtime = st.st_mtime;
872 #ifdef HAVE_INOTIFY
873 if (cnt == hstdb && inotify_fd >= -1)
874 /* We also monitor the resolver configuration file. */
875 resolv_conf_descr = inotify_add_watch (inotify_fd,
876 _PATH_RESCONF,
877 IN_DELETE_SELF | IN_MODIFY);
878 #endif
881 /* Create the socket. */
882 #ifndef __ASSUME_SOCK_CLOEXEC
883 sock = -1;
884 if (have_sock_cloexec >= 0)
885 #endif
887 sock = socket (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
888 #ifndef __ASSUME_SOCK_CLOEXEC
889 if (have_sock_cloexec == 0)
890 have_sock_cloexec = sock != -1 || errno != EINVAL ? 1 : -1;
891 #endif
893 #ifndef __ASSUME_SOCK_CLOEXEC
894 if (have_sock_cloexec < 0)
895 sock = socket (AF_UNIX, SOCK_STREAM, 0);
896 #endif
897 if (sock < 0)
899 dbg_log (_("cannot open socket: %s"), strerror (errno));
900 exit (errno == EACCES ? 4 : 1);
902 /* Bind a name to the socket. */
903 struct sockaddr_un sock_addr;
904 sock_addr.sun_family = AF_UNIX;
905 strcpy (sock_addr.sun_path, _PATH_NSCDSOCKET);
906 if (bind (sock, (struct sockaddr *) &sock_addr, sizeof (sock_addr)) < 0)
908 dbg_log ("%s: %s", _PATH_NSCDSOCKET, strerror (errno));
909 exit (errno == EACCES ? 4 : 1);
912 #ifndef __ASSUME_SOCK_CLOEXEC
913 if (have_sock_cloexec < 0)
915 /* We don't want to get stuck on accept. */
916 int fl = fcntl (sock, F_GETFL);
917 if (fl == -1 || fcntl (sock, F_SETFL, fl | O_NONBLOCK) == -1)
919 dbg_log (_("cannot change socket to nonblocking mode: %s"),
920 strerror (errno));
921 exit (1);
924 /* The descriptor needs to be closed on exec. */
925 if (paranoia && fcntl (sock, F_SETFD, FD_CLOEXEC) == -1)
927 dbg_log (_("cannot set socket to close on exec: %s"),
928 strerror (errno));
929 exit (1);
932 #endif
934 /* Set permissions for the socket. */
935 chmod (_PATH_NSCDSOCKET, DEFFILEMODE);
937 /* Set the socket up to accept connections. */
938 if (listen (sock, SOMAXCONN) < 0)
940 dbg_log (_("cannot enable socket to accept connections: %s"),
941 strerror (errno));
942 exit (1);
945 /* Change to unprivileged uid/gid/groups if specifed in config file */
946 if (server_user != NULL)
947 finish_drop_privileges ();
951 /* Close the connections. */
952 void
953 close_sockets (void)
955 close (sock);
959 static void
960 invalidate_cache (char *key, int fd)
962 dbtype number;
963 int32_t resp;
965 for (number = pwddb; number < lastdb; ++number)
966 if (strcmp (key, dbnames[number]) == 0)
968 if (dbs[number].reset_res)
969 res_init ();
971 break;
974 if (number == lastdb)
976 resp = EINVAL;
977 writeall (fd, &resp, sizeof (resp));
978 return;
981 if (dbs[number].enabled)
983 pthread_mutex_lock (&dbs[number].prune_run_lock);
984 prune_cache (&dbs[number], LONG_MAX, fd);
985 pthread_mutex_unlock (&dbs[number].prune_run_lock);
987 else
989 resp = 0;
990 writeall (fd, &resp, sizeof (resp));
995 #ifdef SCM_RIGHTS
996 static void
997 send_ro_fd (struct database_dyn *db, char *key, int fd)
999 /* If we do not have an read-only file descriptor do nothing. */
1000 if (db->ro_fd == -1)
1001 return;
1003 /* We need to send some data along with the descriptor. */
1004 uint64_t mapsize = (db->head->data_size
1005 + roundup (db->head->module * sizeof (ref_t), ALIGN)
1006 + sizeof (struct database_pers_head));
1007 struct iovec iov[2];
1008 iov[0].iov_base = key;
1009 iov[0].iov_len = strlen (key) + 1;
1010 iov[1].iov_base = &mapsize;
1011 iov[1].iov_len = sizeof (mapsize);
1013 /* Prepare the control message to transfer the descriptor. */
1014 union
1016 struct cmsghdr hdr;
1017 char bytes[CMSG_SPACE (sizeof (int))];
1018 } buf;
1019 struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 2,
1020 .msg_control = buf.bytes,
1021 .msg_controllen = sizeof (buf) };
1022 struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
1024 cmsg->cmsg_level = SOL_SOCKET;
1025 cmsg->cmsg_type = SCM_RIGHTS;
1026 cmsg->cmsg_len = CMSG_LEN (sizeof (int));
1028 *(int *) CMSG_DATA (cmsg) = db->ro_fd;
1030 msg.msg_controllen = cmsg->cmsg_len;
1032 /* Send the control message. We repeat when we are interrupted but
1033 everything else is ignored. */
1034 #ifndef MSG_NOSIGNAL
1035 # define MSG_NOSIGNAL 0
1036 #endif
1037 (void) TEMP_FAILURE_RETRY (sendmsg (fd, &msg, MSG_NOSIGNAL));
1039 if (__builtin_expect (debug_level > 0, 0))
1040 dbg_log (_("provide access to FD %d, for %s"), db->ro_fd, key);
1042 #endif /* SCM_RIGHTS */
1045 /* Handle new request. */
1046 static void
1047 handle_request (int fd, request_header *req, void *key, uid_t uid, pid_t pid)
1049 if (__builtin_expect (req->version, NSCD_VERSION) != NSCD_VERSION)
1051 if (debug_level > 0)
1052 dbg_log (_("\
1053 cannot handle old request version %d; current version is %d"),
1054 req->version, NSCD_VERSION);
1055 return;
1058 /* Perform the SELinux check before we go on to the standard checks. */
1059 if (selinux_enabled && nscd_request_avc_has_perm (fd, req->type) != 0)
1061 if (debug_level > 0)
1063 #ifdef SO_PEERCRED
1064 # ifdef PATH_MAX
1065 char buf[PATH_MAX];
1066 # else
1067 char buf[4096];
1068 # endif
1070 snprintf (buf, sizeof (buf), "/proc/%ld/exe", (long int) pid);
1071 ssize_t n = readlink (buf, buf, sizeof (buf) - 1);
1073 if (n <= 0)
1074 dbg_log (_("\
1075 request from %ld not handled due to missing permission"), (long int) pid);
1076 else
1078 buf[n] = '\0';
1079 dbg_log (_("\
1080 request from '%s' [%ld] not handled due to missing permission"),
1081 buf, (long int) pid);
1083 #else
1084 dbg_log (_("request not handled due to missing permission"));
1085 #endif
1087 return;
1090 struct database_dyn *db = reqinfo[req->type].db;
1092 /* See whether we can service the request from the cache. */
1093 if (__builtin_expect (reqinfo[req->type].data_request, true))
1095 if (__builtin_expect (debug_level, 0) > 0)
1097 if (req->type == GETHOSTBYADDR || req->type == GETHOSTBYADDRv6)
1099 char buf[INET6_ADDRSTRLEN];
1101 dbg_log ("\t%s (%s)", serv2str[req->type],
1102 inet_ntop (req->type == GETHOSTBYADDR
1103 ? AF_INET : AF_INET6,
1104 key, buf, sizeof (buf)));
1106 else
1107 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
1110 /* Is this service enabled? */
1111 if (__builtin_expect (!db->enabled, 0))
1113 /* No, sent the prepared record. */
1114 if (TEMP_FAILURE_RETRY (send (fd, db->disabled_iov->iov_base,
1115 db->disabled_iov->iov_len,
1116 MSG_NOSIGNAL))
1117 != (ssize_t) db->disabled_iov->iov_len
1118 && __builtin_expect (debug_level, 0) > 0)
1120 /* We have problems sending the result. */
1121 char buf[256];
1122 dbg_log (_("cannot write result: %s"),
1123 strerror_r (errno, buf, sizeof (buf)));
1126 return;
1129 /* Be sure we can read the data. */
1130 if (__builtin_expect (pthread_rwlock_tryrdlock (&db->lock) != 0, 0))
1132 ++db->head->rdlockdelayed;
1133 pthread_rwlock_rdlock (&db->lock);
1136 /* See whether we can handle it from the cache. */
1137 struct datahead *cached;
1138 cached = (struct datahead *) cache_search (req->type, key, req->key_len,
1139 db, uid);
1140 if (cached != NULL)
1142 /* Hurray it's in the cache. */
1143 ssize_t nwritten;
1145 #ifdef HAVE_SENDFILE
1146 if (__builtin_expect (db->mmap_used, 1))
1148 assert (db->wr_fd != -1);
1149 assert ((char *) cached->data > (char *) db->data);
1150 assert ((char *) cached->data - (char *) db->head
1151 + cached->recsize
1152 <= (sizeof (struct database_pers_head)
1153 + db->head->module * sizeof (ref_t)
1154 + db->head->data_size));
1155 nwritten = sendfileall (fd, db->wr_fd,
1156 (char *) cached->data
1157 - (char *) db->head, cached->recsize);
1158 # ifndef __ASSUME_SENDFILE
1159 if (nwritten == -1 && errno == ENOSYS)
1160 goto use_write;
1161 # endif
1163 else
1164 # ifndef __ASSUME_SENDFILE
1165 use_write:
1166 # endif
1167 #endif
1168 nwritten = writeall (fd, cached->data, cached->recsize);
1170 if (nwritten != cached->recsize
1171 && __builtin_expect (debug_level, 0) > 0)
1173 /* We have problems sending the result. */
1174 char buf[256];
1175 dbg_log (_("cannot write result: %s"),
1176 strerror_r (errno, buf, sizeof (buf)));
1179 pthread_rwlock_unlock (&db->lock);
1181 return;
1184 pthread_rwlock_unlock (&db->lock);
1186 else if (__builtin_expect (debug_level, 0) > 0)
1188 if (req->type == INVALIDATE)
1189 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
1190 else
1191 dbg_log ("\t%s", serv2str[req->type]);
1194 /* Handle the request. */
1195 switch (req->type)
1197 case GETPWBYNAME:
1198 addpwbyname (db, fd, req, key, uid);
1199 break;
1201 case GETPWBYUID:
1202 addpwbyuid (db, fd, req, key, uid);
1203 break;
1205 case GETGRBYNAME:
1206 addgrbyname (db, fd, req, key, uid);
1207 break;
1209 case GETGRBYGID:
1210 addgrbygid (db, fd, req, key, uid);
1211 break;
1213 case GETHOSTBYNAME:
1214 addhstbyname (db, fd, req, key, uid);
1215 break;
1217 case GETHOSTBYNAMEv6:
1218 addhstbynamev6 (db, fd, req, key, uid);
1219 break;
1221 case GETHOSTBYADDR:
1222 addhstbyaddr (db, fd, req, key, uid);
1223 break;
1225 case GETHOSTBYADDRv6:
1226 addhstbyaddrv6 (db, fd, req, key, uid);
1227 break;
1229 case GETAI:
1230 addhstai (db, fd, req, key, uid);
1231 break;
1233 case INITGROUPS:
1234 addinitgroups (db, fd, req, key, uid);
1235 break;
1237 case GETSERVBYNAME:
1238 addservbyname (db, fd, req, key, uid);
1239 break;
1241 case GETSERVBYPORT:
1242 addservbyport (db, fd, req, key, uid);
1243 break;
1245 case GETSTAT:
1246 case SHUTDOWN:
1247 case INVALIDATE:
1249 /* Get the callers credentials. */
1250 #ifdef SO_PEERCRED
1251 struct ucred caller;
1252 socklen_t optlen = sizeof (caller);
1254 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
1256 char buf[256];
1258 dbg_log (_("error getting caller's id: %s"),
1259 strerror_r (errno, buf, sizeof (buf)));
1260 break;
1263 uid = caller.uid;
1264 #else
1265 /* Some systems have no SO_PEERCRED implementation. They don't
1266 care about security so we don't as well. */
1267 uid = 0;
1268 #endif
1271 /* Accept shutdown, getstat and invalidate only from root. For
1272 the stat call also allow the user specified in the config file. */
1273 if (req->type == GETSTAT)
1275 if (uid == 0 || uid == stat_uid)
1276 send_stats (fd, dbs);
1278 else if (uid == 0)
1280 if (req->type == INVALIDATE)
1281 invalidate_cache (key, fd);
1282 else
1283 termination_handler (0);
1285 break;
1287 case GETFDPW:
1288 case GETFDGR:
1289 case GETFDHST:
1290 case GETFDSERV:
1291 #ifdef SCM_RIGHTS
1292 send_ro_fd (reqinfo[req->type].db, key, fd);
1293 #endif
1294 break;
1296 default:
1297 /* Ignore the command, it's nothing we know. */
1298 break;
1303 /* Restart the process. */
1304 static void
1305 restart (void)
1307 /* First determine the parameters. We do not use the parameters
1308 passed to main() since in case nscd is started by running the
1309 dynamic linker this will not work. Yes, this is not the usual
1310 case but nscd is part of glibc and we occasionally do this. */
1311 size_t buflen = 1024;
1312 char *buf = alloca (buflen);
1313 size_t readlen = 0;
1314 int fd = open ("/proc/self/cmdline", O_RDONLY);
1315 if (fd == -1)
1317 dbg_log (_("\
1318 cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
1319 strerror (errno));
1321 paranoia = 0;
1322 return;
1325 while (1)
1327 ssize_t n = TEMP_FAILURE_RETRY (read (fd, buf + readlen,
1328 buflen - readlen));
1329 if (n == -1)
1331 dbg_log (_("\
1332 cannot read /proc/self/cmdline: %s; disabling paranoia mode"),
1333 strerror (errno));
1335 close (fd);
1336 paranoia = 0;
1337 return;
1340 readlen += n;
1342 if (readlen < buflen)
1343 break;
1345 /* We might have to extend the buffer. */
1346 size_t old_buflen = buflen;
1347 char *newp = extend_alloca (buf, buflen, 2 * buflen);
1348 buf = memmove (newp, buf, old_buflen);
1351 close (fd);
1353 /* Parse the command line. Worst case scenario: every two
1354 characters form one parameter (one character plus NUL). */
1355 char **argv = alloca ((readlen / 2 + 1) * sizeof (argv[0]));
1356 int argc = 0;
1358 char *cp = buf;
1359 while (cp < buf + readlen)
1361 argv[argc++] = cp;
1362 cp = (char *) rawmemchr (cp, '\0') + 1;
1364 argv[argc] = NULL;
1366 /* Second, change back to the old user if we changed it. */
1367 if (server_user != NULL)
1369 if (setresuid (old_uid, old_uid, old_uid) != 0)
1371 dbg_log (_("\
1372 cannot change to old UID: %s; disabling paranoia mode"),
1373 strerror (errno));
1375 paranoia = 0;
1376 return;
1379 if (setresgid (old_gid, old_gid, old_gid) != 0)
1381 dbg_log (_("\
1382 cannot change to old GID: %s; disabling paranoia mode"),
1383 strerror (errno));
1385 setuid (server_uid);
1386 paranoia = 0;
1387 return;
1391 /* Next change back to the old working directory. */
1392 if (chdir (oldcwd) == -1)
1394 dbg_log (_("\
1395 cannot change to old working directory: %s; disabling paranoia mode"),
1396 strerror (errno));
1398 if (server_user != NULL)
1400 setuid (server_uid);
1401 setgid (server_gid);
1403 paranoia = 0;
1404 return;
1407 /* Synchronize memory. */
1408 int32_t certainly[lastdb];
1409 for (int cnt = 0; cnt < lastdb; ++cnt)
1410 if (dbs[cnt].enabled)
1412 /* Make sure nobody keeps using the database. */
1413 dbs[cnt].head->timestamp = 0;
1414 certainly[cnt] = dbs[cnt].head->nscd_certainly_running;
1415 dbs[cnt].head->nscd_certainly_running = 0;
1417 if (dbs[cnt].persistent)
1418 // XXX async OK?
1419 msync (dbs[cnt].head, dbs[cnt].memsize, MS_ASYNC);
1422 /* The preparations are done. */
1423 execv ("/proc/self/exe", argv);
1425 /* If we come here, we will never be able to re-exec. */
1426 dbg_log (_("re-exec failed: %s; disabling paranoia mode"),
1427 strerror (errno));
1429 if (server_user != NULL)
1431 setuid (server_uid);
1432 setgid (server_gid);
1434 if (chdir ("/") != 0)
1435 dbg_log (_("cannot change current working directory to \"/\": %s"),
1436 strerror (errno));
1437 paranoia = 0;
1439 /* Reenable the databases. */
1440 time_t now = time (NULL);
1441 for (int cnt = 0; cnt < lastdb; ++cnt)
1442 if (dbs[cnt].enabled)
1444 dbs[cnt].head->timestamp = now;
1445 dbs[cnt].head->nscd_certainly_running = certainly[cnt];
1450 /* List of file descriptors. */
1451 struct fdlist
1453 int fd;
1454 struct fdlist *next;
1456 /* Memory allocated for the list. */
1457 static struct fdlist *fdlist;
1458 /* List of currently ready-to-read file descriptors. */
1459 static struct fdlist *readylist;
1461 /* Conditional variable and mutex to signal availability of entries in
1462 READYLIST. The condvar is initialized dynamically since we might
1463 use a different clock depending on availability. */
1464 static pthread_cond_t readylist_cond = PTHREAD_COND_INITIALIZER;
1465 static pthread_mutex_t readylist_lock = PTHREAD_MUTEX_INITIALIZER;
1467 /* The clock to use with the condvar. */
1468 static clockid_t timeout_clock = CLOCK_REALTIME;
1470 /* Number of threads ready to handle the READYLIST. */
1471 static unsigned long int nready;
1474 /* Function for the clean-up threads. */
1475 static void *
1476 __attribute__ ((__noreturn__))
1477 nscd_run_prune (void *p)
1479 const long int my_number = (long int) p;
1480 assert (dbs[my_number].enabled);
1482 int dont_need_update = setup_thread (&dbs[my_number]);
1484 time_t now = time (NULL);
1486 /* We are running. */
1487 dbs[my_number].head->timestamp = now;
1489 struct timespec prune_ts;
1490 if (__builtin_expect (clock_gettime (timeout_clock, &prune_ts) == -1, 0))
1491 /* Should never happen. */
1492 abort ();
1494 /* Compute the initial timeout time. Prevent all the timers to go
1495 off at the same time by adding a db-based value. */
1496 prune_ts.tv_sec += CACHE_PRUNE_INTERVAL + my_number;
1497 dbs[my_number].wakeup_time = now + CACHE_PRUNE_INTERVAL + my_number;
1499 pthread_mutex_t *prune_lock = &dbs[my_number].prune_lock;
1500 pthread_mutex_t *prune_run_lock = &dbs[my_number].prune_run_lock;
1501 pthread_cond_t *prune_cond = &dbs[my_number].prune_cond;
1503 pthread_mutex_lock (prune_lock);
1504 while (1)
1506 /* Wait, but not forever. */
1507 int e = 0;
1508 if (! dbs[my_number].clear_cache)
1509 e = pthread_cond_timedwait (prune_cond, prune_lock, &prune_ts);
1510 assert (__builtin_expect (e == 0 || e == ETIMEDOUT, 1));
1512 time_t next_wait;
1513 now = time (NULL);
1514 if (e == ETIMEDOUT || now >= dbs[my_number].wakeup_time
1515 || dbs[my_number].clear_cache)
1517 /* We will determine the new timout values based on the
1518 cache content. Should there be concurrent additions to
1519 the cache which are not accounted for in the cache
1520 pruning we want to know about it. Therefore set the
1521 timeout to the maximum. It will be descreased when adding
1522 new entries to the cache, if necessary. */
1523 if (sizeof (time_t) == sizeof (long int))
1524 dbs[my_number].wakeup_time = LONG_MAX;
1525 else
1526 dbs[my_number].wakeup_time = INT_MAX;
1528 /* Unconditionally reset the flag. */
1529 time_t prune_now = dbs[my_number].clear_cache ? LONG_MAX : now;
1530 dbs[my_number].clear_cache = 0;
1532 pthread_mutex_unlock (prune_lock);
1534 /* We use a separate lock for running the prune function (instead
1535 of keeping prune_lock locked) because this enables concurrent
1536 invocations of cache_add which might modify the timeout value. */
1537 pthread_mutex_lock (prune_run_lock);
1538 next_wait = prune_cache (&dbs[my_number], prune_now, -1);
1539 pthread_mutex_unlock (prune_run_lock);
1541 next_wait = MAX (next_wait, CACHE_PRUNE_INTERVAL);
1542 /* If clients cannot determine for sure whether nscd is running
1543 we need to wake up occasionally to update the timestamp.
1544 Wait 90% of the update period. */
1545 #define UPDATE_MAPPING_TIMEOUT (MAPPING_TIMEOUT * 9 / 10)
1546 if (__builtin_expect (! dont_need_update, 0))
1548 next_wait = MIN (UPDATE_MAPPING_TIMEOUT, next_wait);
1549 dbs[my_number].head->timestamp = now;
1552 pthread_mutex_lock (prune_lock);
1554 /* Make it known when we will wake up again. */
1555 if (now + next_wait < dbs[my_number].wakeup_time)
1556 dbs[my_number].wakeup_time = now + next_wait;
1557 else
1558 next_wait = dbs[my_number].wakeup_time - now;
1560 else
1561 /* The cache was just pruned. Do not do it again now. Just
1562 use the new timeout value. */
1563 next_wait = dbs[my_number].wakeup_time - now;
1565 if (clock_gettime (timeout_clock, &prune_ts) == -1)
1566 /* Should never happen. */
1567 abort ();
1569 /* Compute next timeout time. */
1570 prune_ts.tv_sec += next_wait;
1575 /* This is the main loop. It is replicated in different threads but
1576 the the use of the ready list makes sure only one thread handles an
1577 incoming connection. */
1578 static void *
1579 __attribute__ ((__noreturn__))
1580 nscd_run_worker (void *p)
1582 char buf[256];
1584 /* Initialize the memory-in-flight list. */
1585 for (enum in_flight idx = 0; idx < IDX_last; ++idx)
1586 mem_in_flight.block[idx].dbidx = -1;
1587 /* And queue this threads structure. */
1589 mem_in_flight.next = mem_in_flight_list;
1590 while (atomic_compare_and_exchange_bool_acq (&mem_in_flight_list,
1591 &mem_in_flight,
1592 mem_in_flight.next) != 0);
1594 /* Initial locking. */
1595 pthread_mutex_lock (&readylist_lock);
1597 /* One more thread available. */
1598 ++nready;
1600 while (1)
1602 while (readylist == NULL)
1603 pthread_cond_wait (&readylist_cond, &readylist_lock);
1605 struct fdlist *it = readylist->next;
1606 if (readylist->next == readylist)
1607 /* Just one entry on the list. */
1608 readylist = NULL;
1609 else
1610 readylist->next = it->next;
1612 /* Extract the information and mark the record ready to be used
1613 again. */
1614 int fd = it->fd;
1615 it->next = NULL;
1617 /* One more thread available. */
1618 --nready;
1620 /* We are done with the list. */
1621 pthread_mutex_unlock (&readylist_lock);
1623 #ifndef __ASSUME_ACCEPT4
1624 if (have_accept4 < 0)
1626 /* We do not want to block on a short read or so. */
1627 int fl = fcntl (fd, F_GETFL);
1628 if (fl == -1 || fcntl (fd, F_SETFL, fl | O_NONBLOCK) == -1)
1629 goto close_and_out;
1631 #endif
1633 /* Now read the request. */
1634 request_header req;
1635 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, &req, sizeof (req)))
1636 != sizeof (req), 0))
1638 /* We failed to read data. Note that this also might mean we
1639 failed because we would have blocked. */
1640 if (debug_level > 0)
1641 dbg_log (_("short read while reading request: %s"),
1642 strerror_r (errno, buf, sizeof (buf)));
1643 goto close_and_out;
1646 /* Check whether this is a valid request type. */
1647 if (req.type < GETPWBYNAME || req.type >= LASTREQ)
1648 goto close_and_out;
1650 /* Some systems have no SO_PEERCRED implementation. They don't
1651 care about security so we don't as well. */
1652 uid_t uid = -1;
1653 #ifdef SO_PEERCRED
1654 pid_t pid = 0;
1656 if (__builtin_expect (debug_level > 0, 0))
1658 struct ucred caller;
1659 socklen_t optlen = sizeof (caller);
1661 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) == 0)
1662 pid = caller.pid;
1664 #else
1665 const pid_t pid = 0;
1666 #endif
1668 /* It should not be possible to crash the nscd with a silly
1669 request (i.e., a terribly large key). We limit the size to 1kb. */
1670 if (__builtin_expect (req.key_len, 1) < 0
1671 || __builtin_expect (req.key_len, 1) > MAXKEYLEN)
1673 if (debug_level > 0)
1674 dbg_log (_("key length in request too long: %d"), req.key_len);
1676 else
1678 /* Get the key. */
1679 char keybuf[MAXKEYLEN];
1681 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, keybuf,
1682 req.key_len))
1683 != req.key_len, 0))
1685 /* Again, this can also mean we would have blocked. */
1686 if (debug_level > 0)
1687 dbg_log (_("short read while reading request key: %s"),
1688 strerror_r (errno, buf, sizeof (buf)));
1689 goto close_and_out;
1692 if (__builtin_expect (debug_level, 0) > 0)
1694 #ifdef SO_PEERCRED
1695 if (pid != 0)
1696 dbg_log (_("\
1697 handle_request: request received (Version = %d) from PID %ld"),
1698 req.version, (long int) pid);
1699 else
1700 #endif
1701 dbg_log (_("\
1702 handle_request: request received (Version = %d)"), req.version);
1705 /* Phew, we got all the data, now process it. */
1706 handle_request (fd, &req, keybuf, uid, pid);
1709 close_and_out:
1710 /* We are done. */
1711 close (fd);
1713 /* Re-locking. */
1714 pthread_mutex_lock (&readylist_lock);
1716 /* One more thread available. */
1717 ++nready;
1722 static unsigned int nconns;
1724 static void
1725 fd_ready (int fd)
1727 pthread_mutex_lock (&readylist_lock);
1729 /* Find an empty entry in FDLIST. */
1730 size_t inner;
1731 for (inner = 0; inner < nconns; ++inner)
1732 if (fdlist[inner].next == NULL)
1733 break;
1734 assert (inner < nconns);
1736 fdlist[inner].fd = fd;
1738 if (readylist == NULL)
1739 readylist = fdlist[inner].next = &fdlist[inner];
1740 else
1742 fdlist[inner].next = readylist->next;
1743 readylist = readylist->next = &fdlist[inner];
1746 bool do_signal = true;
1747 if (__builtin_expect (nready == 0, 0))
1749 ++client_queued;
1750 do_signal = false;
1752 /* Try to start another thread to help out. */
1753 pthread_t th;
1754 if (nthreads < max_nthreads
1755 && pthread_create (&th, &attr, nscd_run_worker,
1756 (void *) (long int) nthreads) == 0)
1758 /* We got another thread. */
1759 ++nthreads;
1760 /* The new thread might need a kick. */
1761 do_signal = true;
1766 pthread_mutex_unlock (&readylist_lock);
1768 /* Tell one of the worker threads there is work to do. */
1769 if (do_signal)
1770 pthread_cond_signal (&readylist_cond);
1774 /* Check whether restarting should happen. */
1775 static inline int
1776 restart_p (time_t now)
1778 return (paranoia && readylist == NULL && nready == nthreads
1779 && now >= restart_time);
1783 /* Array for times a connection was accepted. */
1784 static time_t *starttime;
1787 static void
1788 __attribute__ ((__noreturn__))
1789 main_loop_poll (void)
1791 struct pollfd *conns = (struct pollfd *) xmalloc (nconns
1792 * sizeof (conns[0]));
1794 conns[0].fd = sock;
1795 conns[0].events = POLLRDNORM;
1796 size_t nused = 1;
1797 size_t firstfree = 1;
1799 #ifdef HAVE_INOTIFY
1800 if (inotify_fd != -1)
1802 conns[1].fd = inotify_fd;
1803 conns[1].events = POLLRDNORM;
1804 nused = 2;
1805 firstfree = 2;
1807 #endif
1809 while (1)
1811 /* Wait for any event. We wait at most a couple of seconds so
1812 that we can check whether we should close any of the accepted
1813 connections since we have not received a request. */
1814 #define MAX_ACCEPT_TIMEOUT 30
1815 #define MIN_ACCEPT_TIMEOUT 5
1816 #define MAIN_THREAD_TIMEOUT \
1817 (MAX_ACCEPT_TIMEOUT * 1000 \
1818 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * 1000 * nused) / (2 * nconns))
1820 int n = poll (conns, nused, MAIN_THREAD_TIMEOUT);
1822 time_t now = time (NULL);
1824 /* If there is a descriptor ready for reading or there is a new
1825 connection, process this now. */
1826 if (n > 0)
1828 if (conns[0].revents != 0)
1830 /* We have a new incoming connection. Accept the connection. */
1831 int fd;
1833 #ifndef __ASSUME_ACCEPT4
1834 fd = -1;
1835 if (have_accept4 >= 0)
1836 #endif
1838 fd = TEMP_FAILURE_RETRY (accept4 (sock, NULL, NULL,
1839 SOCK_NONBLOCK));
1840 #ifndef __ASSUME_ACCEPT4
1841 if (have_accept4 == 0)
1842 have_accept4 = fd != -1 || errno != ENOSYS ? 1 : -1;
1843 #endif
1845 #ifndef __ASSUME_ACCEPT4
1846 if (have_accept4 < 0)
1847 fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
1848 #endif
1850 /* Use the descriptor if we have not reached the limit. */
1851 if (fd >= 0)
1853 if (firstfree < nconns)
1855 conns[firstfree].fd = fd;
1856 conns[firstfree].events = POLLRDNORM;
1857 starttime[firstfree] = now;
1858 if (firstfree >= nused)
1859 nused = firstfree + 1;
1862 ++firstfree;
1863 while (firstfree < nused && conns[firstfree].fd != -1);
1865 else
1866 /* We cannot use the connection so close it. */
1867 close (fd);
1870 --n;
1873 size_t first = 1;
1874 #ifdef HAVE_INOTIFY
1875 if (inotify_fd != -1 && conns[1].fd == inotify_fd)
1877 if (conns[1].revents != 0)
1879 bool to_clear[lastdb] = { false, };
1880 union
1882 # ifndef PATH_MAX
1883 # define PATH_MAX 1024
1884 # endif
1885 struct inotify_event i;
1886 char buf[sizeof (struct inotify_event) + PATH_MAX];
1887 } inev;
1889 while (1)
1891 ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev,
1892 sizeof (inev)));
1893 if (nb < (ssize_t) sizeof (struct inotify_event))
1895 if (__builtin_expect (nb == -1 && errno != EAGAIN,
1898 /* Something went wrong when reading the inotify
1899 data. Better disable inotify. */
1900 dbg_log (_("\
1901 disabled inotify after read error %d"),
1902 errno);
1903 conns[1].fd = -1;
1904 firstfree = 1;
1905 if (nused == 2)
1906 nused = 1;
1907 close (inotify_fd);
1908 inotify_fd = -1;
1910 break;
1913 /* Check which of the files changed. */
1914 for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
1915 if (inev.i.wd == dbs[dbcnt].inotify_descr)
1917 to_clear[dbcnt] = true;
1918 goto next;
1921 if (inev.i.wd == resolv_conf_descr)
1923 res_init ();
1924 to_clear[hstdb] = true;
1926 next:;
1929 /* Actually perform the cache clearing. */
1930 for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
1931 if (to_clear[dbcnt])
1933 pthread_mutex_lock (&dbs[dbcnt].prune_lock);
1934 dbs[dbcnt].clear_cache = 1;
1935 pthread_mutex_unlock (&dbs[dbcnt].prune_lock);
1936 pthread_cond_signal (&dbs[dbcnt].prune_cond);
1939 --n;
1942 first = 2;
1944 #endif
1946 for (size_t cnt = first; cnt < nused && n > 0; ++cnt)
1947 if (conns[cnt].revents != 0)
1949 fd_ready (conns[cnt].fd);
1951 /* Clean up the CONNS array. */
1952 conns[cnt].fd = -1;
1953 if (cnt < firstfree)
1954 firstfree = cnt;
1955 if (cnt == nused - 1)
1957 --nused;
1958 while (conns[nused - 1].fd == -1);
1960 --n;
1964 /* Now find entries which have timed out. */
1965 assert (nused > 0);
1967 /* We make the timeout length depend on the number of file
1968 descriptors currently used. */
1969 #define ACCEPT_TIMEOUT \
1970 (MAX_ACCEPT_TIMEOUT \
1971 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * nused) / nconns)
1972 time_t laststart = now - ACCEPT_TIMEOUT;
1974 for (size_t cnt = nused - 1; cnt > 0; --cnt)
1976 if (conns[cnt].fd != -1 && starttime[cnt] < laststart)
1978 /* Remove the entry, it timed out. */
1979 (void) close (conns[cnt].fd);
1980 conns[cnt].fd = -1;
1982 if (cnt < firstfree)
1983 firstfree = cnt;
1984 if (cnt == nused - 1)
1986 --nused;
1987 while (conns[nused - 1].fd == -1);
1991 if (restart_p (now))
1992 restart ();
1997 #ifdef HAVE_EPOLL
1998 static void
1999 main_loop_epoll (int efd)
2001 struct epoll_event ev = { 0, };
2002 int nused = 1;
2003 size_t highest = 0;
2005 /* Add the socket. */
2006 ev.events = EPOLLRDNORM;
2007 ev.data.fd = sock;
2008 if (epoll_ctl (efd, EPOLL_CTL_ADD, sock, &ev) == -1)
2009 /* We cannot use epoll. */
2010 return;
2012 # ifdef HAVE_INOTIFY
2013 if (inotify_fd != -1)
2015 ev.events = EPOLLRDNORM;
2016 ev.data.fd = inotify_fd;
2017 if (epoll_ctl (efd, EPOLL_CTL_ADD, inotify_fd, &ev) == -1)
2018 /* We cannot use epoll. */
2019 return;
2020 nused = 2;
2022 # endif
2024 while (1)
2026 struct epoll_event revs[100];
2027 # define nrevs (sizeof (revs) / sizeof (revs[0]))
2029 int n = epoll_wait (efd, revs, nrevs, MAIN_THREAD_TIMEOUT);
2031 time_t now = time (NULL);
2033 for (int cnt = 0; cnt < n; ++cnt)
2034 if (revs[cnt].data.fd == sock)
2036 /* A new connection. */
2037 int fd;
2039 # ifndef __ASSUME_ACCEPT4
2040 fd = -1;
2041 if (have_accept4 >= 0)
2042 # endif
2044 fd = TEMP_FAILURE_RETRY (accept4 (sock, NULL, NULL,
2045 SOCK_NONBLOCK));
2046 # ifndef __ASSUME_ACCEPT4
2047 if (have_accept4 == 0)
2048 have_accept4 = fd != -1 || errno != ENOSYS ? 1 : -1;
2049 # endif
2051 # ifndef __ASSUME_ACCEPT4
2052 if (have_accept4 < 0)
2053 fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
2054 # endif
2056 /* Use the descriptor if we have not reached the limit. */
2057 if (fd >= 0)
2059 /* Try to add the new descriptor. */
2060 ev.data.fd = fd;
2061 if (fd >= nconns
2062 || epoll_ctl (efd, EPOLL_CTL_ADD, fd, &ev) == -1)
2063 /* The descriptor is too large or something went
2064 wrong. Close the descriptor. */
2065 close (fd);
2066 else
2068 /* Remember when we accepted the connection. */
2069 starttime[fd] = now;
2071 if (fd > highest)
2072 highest = fd;
2074 ++nused;
2078 # ifdef HAVE_INOTIFY
2079 else if (revs[cnt].data.fd == inotify_fd)
2081 bool to_clear[lastdb] = { false, };
2082 union
2084 struct inotify_event i;
2085 char buf[sizeof (struct inotify_event) + PATH_MAX];
2086 } inev;
2088 while (1)
2090 ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev,
2091 sizeof (inev)));
2092 if (nb < (ssize_t) sizeof (struct inotify_event))
2094 if (__builtin_expect (nb == -1 && errno != EAGAIN, 0))
2096 /* Something went wrong when reading the inotify
2097 data. Better disable inotify. */
2098 dbg_log (_("disabled inotify after read error %d"),
2099 errno);
2100 (void) epoll_ctl (efd, EPOLL_CTL_DEL, inotify_fd,
2101 NULL);
2102 close (inotify_fd);
2103 inotify_fd = -1;
2105 break;
2108 /* Check which of the files changed. */
2109 for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
2110 if (inev.i.wd == dbs[dbcnt].inotify_descr)
2112 to_clear[dbcnt] = true;
2113 goto next;
2116 if (inev.i.wd == resolv_conf_descr)
2118 res_init ();
2119 to_clear[hstdb] = true;
2121 next:;
2124 /* Actually perform the cache clearing. */
2125 for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
2126 if (to_clear[dbcnt])
2128 pthread_mutex_lock (&dbs[dbcnt].prune_lock);
2129 dbs[dbcnt].clear_cache = 1;
2130 pthread_mutex_unlock (&dbs[dbcnt].prune_lock);
2131 pthread_cond_signal (&dbs[dbcnt].prune_cond);
2134 # endif
2135 else
2137 /* Remove the descriptor from the epoll descriptor. */
2138 (void) epoll_ctl (efd, EPOLL_CTL_DEL, revs[cnt].data.fd, NULL);
2140 /* Get a worker to handle the request. */
2141 fd_ready (revs[cnt].data.fd);
2143 /* Reset the time. */
2144 starttime[revs[cnt].data.fd] = 0;
2145 if (revs[cnt].data.fd == highest)
2147 --highest;
2148 while (highest > 0 && starttime[highest] == 0);
2150 --nused;
2153 /* Now look for descriptors for accepted connections which have
2154 no reply in too long of a time. */
2155 time_t laststart = now - ACCEPT_TIMEOUT;
2156 assert (starttime[sock] == 0);
2157 assert (inotify_fd == -1 || starttime[inotify_fd] == 0);
2158 for (int cnt = highest; cnt > STDERR_FILENO; --cnt)
2159 if (starttime[cnt] != 0 && starttime[cnt] < laststart)
2161 /* We are waiting for this one for too long. Close it. */
2162 (void) epoll_ctl (efd, EPOLL_CTL_DEL, cnt, NULL);
2164 (void) close (cnt);
2166 starttime[cnt] = 0;
2167 if (cnt == highest)
2168 --highest;
2170 else if (cnt != sock && starttime[cnt] == 0 && cnt == highest)
2171 --highest;
2173 if (restart_p (now))
2174 restart ();
2177 #endif
2180 /* Start all the threads we want. The initial process is thread no. 1. */
2181 void
2182 start_threads (void)
2184 /* Initialize the conditional variable we will use. The only
2185 non-standard attribute we might use is the clock selection. */
2186 pthread_condattr_t condattr;
2187 pthread_condattr_init (&condattr);
2189 #if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0 \
2190 && defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
2191 /* Determine whether the monotonous clock is available. */
2192 struct timespec dummy;
2193 # if _POSIX_MONOTONIC_CLOCK == 0
2194 if (sysconf (_SC_MONOTONIC_CLOCK) > 0)
2195 # endif
2196 # if _POSIX_CLOCK_SELECTION == 0
2197 if (sysconf (_SC_CLOCK_SELECTION) > 0)
2198 # endif
2199 if (clock_getres (CLOCK_MONOTONIC, &dummy) == 0
2200 && pthread_condattr_setclock (&condattr, CLOCK_MONOTONIC) == 0)
2201 timeout_clock = CLOCK_MONOTONIC;
2202 #endif
2204 /* Create the attribute for the threads. They are all created
2205 detached. */
2206 pthread_attr_init (&attr);
2207 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
2208 /* Use 1MB stacks, twice as much for 64-bit architectures. */
2209 pthread_attr_setstacksize (&attr, NSCD_THREAD_STACKSIZE);
2211 /* We allow less than LASTDB threads only for debugging. */
2212 if (debug_level == 0)
2213 nthreads = MAX (nthreads, lastdb);
2215 /* Create the threads which prune the databases. */
2216 // XXX Ideally this work would be done by some of the worker threads.
2217 // XXX But this is problematic since we would need to be able to wake
2218 // XXX them up explicitly as well as part of the group handling the
2219 // XXX ready-list. This requires an operation where we can wait on
2220 // XXX two conditional variables at the same time. This operation
2221 // XXX does not exist (yet).
2222 for (long int i = 0; i < lastdb; ++i)
2224 /* Initialize the conditional variable. */
2225 if (pthread_cond_init (&dbs[i].prune_cond, &condattr) != 0)
2227 dbg_log (_("could not initialize conditional variable"));
2228 exit (1);
2231 pthread_t th;
2232 if (dbs[i].enabled
2233 && pthread_create (&th, &attr, nscd_run_prune, (void *) i) != 0)
2235 dbg_log (_("could not start clean-up thread; terminating"));
2236 exit (1);
2240 pthread_condattr_destroy (&condattr);
2242 for (long int i = 0; i < nthreads; ++i)
2244 pthread_t th;
2245 if (pthread_create (&th, &attr, nscd_run_worker, NULL) != 0)
2247 if (i == 0)
2249 dbg_log (_("could not start any worker thread; terminating"));
2250 exit (1);
2253 break;
2257 /* Determine how much room for descriptors we should initially
2258 allocate. This might need to change later if we cap the number
2259 with MAXCONN. */
2260 const long int nfds = sysconf (_SC_OPEN_MAX);
2261 #define MINCONN 32
2262 #define MAXCONN 16384
2263 if (nfds == -1 || nfds > MAXCONN)
2264 nconns = MAXCONN;
2265 else if (nfds < MINCONN)
2266 nconns = MINCONN;
2267 else
2268 nconns = nfds;
2270 /* We need memory to pass descriptors on to the worker threads. */
2271 fdlist = (struct fdlist *) xcalloc (nconns, sizeof (fdlist[0]));
2272 /* Array to keep track when connection was accepted. */
2273 starttime = (time_t *) xcalloc (nconns, sizeof (starttime[0]));
2275 /* In the main thread we execute the loop which handles incoming
2276 connections. */
2277 #ifdef HAVE_EPOLL
2278 int efd = epoll_create (100);
2279 if (efd != -1)
2281 main_loop_epoll (efd);
2282 close (efd);
2284 #endif
2286 main_loop_poll ();
2290 /* Look up the uid, gid, and supplementary groups to run nscd as. When
2291 this function is called, we are not listening on the nscd socket yet so
2292 we can just use the ordinary lookup functions without causing a lockup */
2293 static void
2294 begin_drop_privileges (void)
2296 struct passwd *pwd = getpwnam (server_user);
2298 if (pwd == NULL)
2300 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
2301 error (EXIT_FAILURE, 0, _("Failed to run nscd as user '%s'"),
2302 server_user);
2305 server_uid = pwd->pw_uid;
2306 server_gid = pwd->pw_gid;
2308 /* Save the old UID/GID if we have to change back. */
2309 if (paranoia)
2311 old_uid = getuid ();
2312 old_gid = getgid ();
2315 if (getgrouplist (server_user, server_gid, NULL, &server_ngroups) == 0)
2317 /* This really must never happen. */
2318 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
2319 error (EXIT_FAILURE, errno, _("initial getgrouplist failed"));
2322 server_groups = (gid_t *) xmalloc (server_ngroups * sizeof (gid_t));
2324 if (getgrouplist (server_user, server_gid, server_groups, &server_ngroups)
2325 == -1)
2327 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
2328 error (EXIT_FAILURE, errno, _("getgrouplist failed"));
2333 /* Call setgroups(), setgid(), and setuid() to drop root privileges and
2334 run nscd as the user specified in the configuration file. */
2335 static void
2336 finish_drop_privileges (void)
2338 #if defined HAVE_LIBAUDIT && defined HAVE_LIBCAP
2339 /* We need to preserve the capabilities to connect to the audit daemon. */
2340 cap_t new_caps = preserve_capabilities ();
2341 #endif
2343 if (setgroups (server_ngroups, server_groups) == -1)
2345 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
2346 error (EXIT_FAILURE, errno, _("setgroups failed"));
2349 int res;
2350 if (paranoia)
2351 res = setresgid (server_gid, server_gid, old_gid);
2352 else
2353 res = setgid (server_gid);
2354 if (res == -1)
2356 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
2357 perror ("setgid");
2358 exit (4);
2361 if (paranoia)
2362 res = setresuid (server_uid, server_uid, old_uid);
2363 else
2364 res = setuid (server_uid);
2365 if (res == -1)
2367 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
2368 perror ("setuid");
2369 exit (4);
2372 #if defined HAVE_LIBAUDIT && defined HAVE_LIBCAP
2373 /* Remove the temporary capabilities. */
2374 install_real_capabilities (new_caps);
2375 #endif