]> git.ipfire.org Git - thirdparty/glibc.git/blame - nscd/connections.c
* nscd/connections.c (handle_request): Fix thinko in selinux test
[thirdparty/glibc.git] / nscd / connections.c
CommitLineData
67479a70 1/* Inner loops of cache daemon.
43397eaf 2 Copyright (C) 1998-2003, 2004, 2005, 2006, 2007 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
UD
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation.
d67281a7 9
43bc8ac6 10 This program is distributed in the hope that it will be useful,
d67281a7 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
43bc8ac6
UD
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
d67281a7 14
43bc8ac6
UD
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
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>
a95a08b4 26#include <libintl.h>
d67281a7 27#include <pthread.h>
057685e4 28#include <pwd.h>
482bbeb9 29#include <resolv.h>
057685e4 30#include <stdio.h>
d67281a7
UD
31#include <stdlib.h>
32#include <unistd.h>
8d8c6efa 33#include <arpa/inet.h>
fc03df7a
UD
34#ifdef HAVE_EPOLL
35# include <sys/epoll.h>
36#endif
a95a08b4 37#include <sys/mman.h>
67479a70 38#include <sys/param.h>
a53bad16 39#include <sys/poll.h>
eac10791
UD
40#ifdef HAVE_SENDFILE
41# include <sys/sendfile.h>
42#endif
d67281a7
UD
43#include <sys/socket.h>
44#include <sys/stat.h>
d67281a7
UD
45#include <sys/un.h>
46
47#include "nscd.h"
48#include "dbg_log.h"
74a30a58 49#include "selinux.h"
eac10791
UD
50#ifdef HAVE_SENDFILE
51# include <kernel-features.h>
52#endif
a334319f
UD
53
54
057685e4
UD
55/* Wrapper functions with error checking for standard functions. */
56extern void *xmalloc (size_t n);
57extern void *xcalloc (size_t n, size_t s);
58extern void *xrealloc (void *o, size_t n);
59
60/* Support to run nscd as an unprivileged user */
61const char *server_user;
62static uid_t server_uid;
63static gid_t server_gid;
a12ce44f
UD
64const char *stat_user;
65uid_t stat_uid;
057685e4
UD
66static gid_t *server_groups;
67#ifndef NGROUPS
68# define NGROUPS 32
69#endif
a95a08b4 70static int server_ngroups;
057685e4 71
27e82856
UD
72static pthread_attr_t attr;
73
057685e4
UD
74static void begin_drop_privileges (void);
75static void finish_drop_privileges (void);
76
67479a70 77/* Map request type to a string. */
b21fa963 78const char *const serv2str[LASTREQ] =
d67281a7 79{
67479a70
UD
80 [GETPWBYNAME] = "GETPWBYNAME",
81 [GETPWBYUID] = "GETPWBYUID",
82 [GETGRBYNAME] = "GETGRBYNAME",
83 [GETGRBYGID] = "GETGRBYGID",
84 [GETHOSTBYNAME] = "GETHOSTBYNAME",
85 [GETHOSTBYNAMEv6] = "GETHOSTBYNAMEv6",
86 [GETHOSTBYADDR] = "GETHOSTBYADDR",
87 [GETHOSTBYADDRv6] = "GETHOSTBYADDRv6",
88 [SHUTDOWN] = "SHUTDOWN",
756409c4 89 [GETSTAT] = "GETSTAT",
c207f23b
UD
90 [INVALIDATE] = "INVALIDATE",
91 [GETFDPW] = "GETFDPW",
92 [GETFDGR] = "GETFDGR",
d19687d6 93 [GETFDHST] = "GETFDHST",
f7e7a396 94 [GETAI] = "GETAI",
b21fa963
UD
95 [INITGROUPS] = "INITGROUPS",
96 [GETSERVBYNAME] = "GETSERVBYNAME",
97 [GETSERVBYPORT] = "GETSERVBYPORT",
98 [GETFDSERV] = "GETFDSERV"
67479a70
UD
99};
100
101/* The control data structures for the services. */
a95a08b4 102struct database_dyn dbs[lastdb] =
67479a70
UD
103{
104 [pwddb] = {
c2e13112 105 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
cabfcde1 106 .prunelock = PTHREAD_MUTEX_INITIALIZER,
c2e13112
RM
107 .enabled = 0,
108 .check_file = 1,
a95a08b4 109 .persistent = 0,
797ed6f7 110 .propagate = 1,
c207f23b 111 .shared = 0,
2c210d1e 112 .max_db_size = DEFAULT_MAX_DB_SIZE,
b21fa963 113 .reset_res = 0,
c2e13112 114 .filename = "/etc/passwd",
a95a08b4 115 .db_filename = _PATH_NSCD_PASSWD_DB,
c2e13112
RM
116 .disabled_iov = &pwd_iov_disabled,
117 .postimeout = 3600,
a95a08b4
UD
118 .negtimeout = 20,
119 .wr_fd = -1,
120 .ro_fd = -1,
121 .mmap_used = false
67479a70
UD
122 },
123 [grpdb] = {
c2e13112 124 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
cabfcde1 125 .prunelock = PTHREAD_MUTEX_INITIALIZER,
c2e13112
RM
126 .enabled = 0,
127 .check_file = 1,
a95a08b4 128 .persistent = 0,
797ed6f7 129 .propagate = 1,
c207f23b 130 .shared = 0,
2c210d1e 131 .max_db_size = DEFAULT_MAX_DB_SIZE,
b21fa963 132 .reset_res = 0,
c2e13112 133 .filename = "/etc/group",
a95a08b4 134 .db_filename = _PATH_NSCD_GROUP_DB,
c2e13112
RM
135 .disabled_iov = &grp_iov_disabled,
136 .postimeout = 3600,
a95a08b4
UD
137 .negtimeout = 60,
138 .wr_fd = -1,
139 .ro_fd = -1,
140 .mmap_used = false
67479a70
UD
141 },
142 [hstdb] = {
c2e13112 143 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
cabfcde1 144 .prunelock = PTHREAD_MUTEX_INITIALIZER,
c2e13112
RM
145 .enabled = 0,
146 .check_file = 1,
a95a08b4 147 .persistent = 0,
797ed6f7 148 .propagate = 0, /* Not used. */
c207f23b 149 .shared = 0,
2c210d1e 150 .max_db_size = DEFAULT_MAX_DB_SIZE,
b21fa963 151 .reset_res = 1,
c2e13112 152 .filename = "/etc/hosts",
a95a08b4 153 .db_filename = _PATH_NSCD_HOSTS_DB,
c2e13112
RM
154 .disabled_iov = &hst_iov_disabled,
155 .postimeout = 3600,
a95a08b4
UD
156 .negtimeout = 20,
157 .wr_fd = -1,
158 .ro_fd = -1,
159 .mmap_used = false
b21fa963
UD
160 },
161 [servdb] = {
162 .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
163 .prunelock = PTHREAD_MUTEX_INITIALIZER,
164 .enabled = 0,
165 .check_file = 1,
166 .persistent = 0,
167 .propagate = 0, /* Not used. */
168 .shared = 0,
169 .max_db_size = DEFAULT_MAX_DB_SIZE,
170 .reset_res = 0,
171 .filename = "/etc/services",
172 .db_filename = _PATH_NSCD_SERVICES_DB,
173 .disabled_iov = &serv_iov_disabled,
174 .postimeout = 28800,
175 .negtimeout = 20,
176 .wr_fd = -1,
177 .ro_fd = -1,
178 .mmap_used = false
67479a70
UD
179 }
180};
d67281a7 181
a95a08b4
UD
182
183/* Mapping of request type to database. */
c207f23b 184static struct database_dyn *const serv2db[LASTREQ] =
a95a08b4
UD
185{
186 [GETPWBYNAME] = &dbs[pwddb],
187 [GETPWBYUID] = &dbs[pwddb],
188 [GETGRBYNAME] = &dbs[grpdb],
189 [GETGRBYGID] = &dbs[grpdb],
190 [GETHOSTBYNAME] = &dbs[hstdb],
191 [GETHOSTBYNAMEv6] = &dbs[hstdb],
192 [GETHOSTBYADDR] = &dbs[hstdb],
c207f23b
UD
193 [GETHOSTBYADDRv6] = &dbs[hstdb],
194 [GETFDPW] = &dbs[pwddb],
195 [GETFDGR] = &dbs[grpdb],
196 [GETFDHST] = &dbs[hstdb],
d19687d6 197 [GETAI] = &dbs[hstdb],
b21fa963
UD
198 [INITGROUPS] = &dbs[grpdb],
199 [GETSERVBYNAME] = &dbs[servdb],
200 [GETSERVBYPORT] = &dbs[servdb],
201 [GETFDSERV] = &dbs[servdb]
a95a08b4
UD
202};
203
204
34489d95
UD
205/* Number of seconds between two cache pruning runs. */
206#define CACHE_PRUNE_INTERVAL 15
207
a95a08b4 208
27e82856 209/* Initial number of threads to use. */
67479a70 210int nthreads = -1;
27e82856
UD
211/* Maximum number of threads to use. */
212int max_nthreads = 32;
d67281a7 213
67479a70
UD
214/* Socket for incoming connections. */
215static int sock;
d67281a7 216
0fdb4f42
UD
217/* Number of times clients had to wait. */
218unsigned long int client_queued;
219
d67281a7 220
d2dc7d84
UD
221ssize_t
222writeall (int fd, const void *buf, size_t len)
223{
224 size_t n = len;
225 ssize_t ret;
226 do
227 {
2c210d1e 228 ret = TEMP_FAILURE_RETRY (send (fd, buf, n, MSG_NOSIGNAL));
d2dc7d84
UD
229 if (ret <= 0)
230 break;
231 buf = (const char *) buf + ret;
232 n -= ret;
233 }
234 while (n > 0);
235 return ret < 0 ? ret : len - n;
236}
237
238
bd547139
UD
239#ifdef HAVE_SENDFILE
240ssize_t
241sendfileall (int tofd, int fromfd, off_t off, size_t len)
242{
243 ssize_t n = len;
244 ssize_t ret;
245
246 do
247 {
248 ret = TEMP_FAILURE_RETRY (sendfile (tofd, fromfd, &off, n));
249 if (ret <= 0)
250 break;
251 n -= ret;
252 }
253 while (n > 0);
254 return ret < 0 ? ret : len - n;
255}
256#endif
257
258
dc4bb1c2
UD
259enum usekey
260 {
261 use_not = 0,
262 /* The following three are not really used, they are symbolic constants. */
263 use_first = 16,
264 use_begin = 32,
265 use_end = 64,
266
267 use_he = 1,
268 use_he_begin = use_he | use_begin,
269 use_he_end = use_he | use_end,
270#if SEPARATE_KEY
271 use_key = 2,
272 use_key_begin = use_key | use_begin,
273 use_key_end = use_key | use_end,
274 use_key_first = use_key_begin | use_first,
275#endif
276 use_data = 3,
277 use_data_begin = use_data | use_begin,
278 use_data_end = use_data | use_end,
279 use_data_first = use_data_begin | use_first
280 };
281
282
283static int
284check_use (const char *data, nscd_ssize_t first_free, uint8_t *usemap,
285 enum usekey use, ref_t start, size_t len)
286{
287 assert (len >= 2);
288
289 if (start > first_free || start + len > first_free
290 || (start & BLOCK_ALIGN_M1))
291 return 0;
292
293 if (usemap[start] == use_not)
294 {
295 /* Add the start marker. */
296 usemap[start] = use | use_begin;
297 use &= ~use_first;
298
299 while (--len > 0)
300 if (usemap[++start] != use_not)
301 return 0;
302 else
303 usemap[start] = use;
304
305 /* Add the end marker. */
306 usemap[start] = use | use_end;
307 }
308 else if ((usemap[start] & ~use_first) == ((use | use_begin) & ~use_first))
309 {
310 /* Hash entries can't be shared. */
311 if (use == use_he)
312 return 0;
313
314 usemap[start] |= (use & use_first);
315 use &= ~use_first;
316
317 while (--len > 1)
318 if (usemap[++start] != use)
319 return 0;
320
321 if (usemap[++start] != (use | use_end))
322 return 0;
323 }
324 else
325 /* Points to a wrong object or somewhere in the middle. */
326 return 0;
327
328 return 1;
329}
330
331
332/* Verify data in persistent database. */
333static int
334verify_persistent_db (void *mem, struct database_pers_head *readhead, int dbnr)
335{
b21fa963 336 assert (dbnr == pwddb || dbnr == grpdb || dbnr == hstdb || dbnr == servdb);
dc4bb1c2
UD
337
338 time_t now = time (NULL);
339
340 struct database_pers_head *head = mem;
341 struct database_pers_head head_copy = *head;
342
343 /* Check that the header that was read matches the head in the database. */
344 if (readhead != NULL && memcmp (head, readhead, sizeof (*head)) != 0)
345 return 0;
346
347 /* First some easy tests: make sure the database header is sane. */
348 if (head->version != DB_VERSION
349 || head->header_size != sizeof (*head)
350 /* We allow a timestamp to be one hour ahead of the current time.
351 This should cover daylight saving time changes. */
352 || head->timestamp > now + 60 * 60 + 60
353 || (head->gc_cycle & 1)
354 || (size_t) head->module > INT32_MAX / sizeof (ref_t)
355 || (size_t) head->data_size > INT32_MAX - head->module * sizeof (ref_t)
356 || head->first_free < 0
357 || head->first_free > head->data_size
358 || (head->first_free & BLOCK_ALIGN_M1) != 0
359 || head->maxnentries < 0
360 || head->maxnsearched < 0)
361 return 0;
362
363 uint8_t *usemap = calloc (head->first_free, 1);
364 if (usemap == NULL)
365 return 0;
366
367 const char *data = (char *) &head->array[roundup (head->module,
368 ALIGN / sizeof (ref_t))];
369
370 nscd_ssize_t he_cnt = 0;
371 for (nscd_ssize_t cnt = 0; cnt < head->module; ++cnt)
372 {
373 ref_t work = head->array[cnt];
374
375 while (work != ENDREF)
376 {
377 if (! check_use (data, head->first_free, usemap, use_he, work,
378 sizeof (struct hashentry)))
379 goto fail;
380
381 /* Now we know we can dereference the record. */
382 struct hashentry *here = (struct hashentry *) (data + work);
383
384 ++he_cnt;
385
386 /* Make sure the record is for this type of service. */
387 if (here->type >= LASTREQ
388 || serv2db[here->type] != &dbs[dbnr])
389 goto fail;
390
391 /* Validate boolean field value. */
392 if (here->first != false && here->first != true)
393 goto fail;
394
395 if (here->len < 0)
396 goto fail;
397
398 /* Now the data. */
399 if (here->packet < 0
400 || here->packet > head->first_free
401 || here->packet + sizeof (struct datahead) > head->first_free)
402 goto fail;
403
404 struct datahead *dh = (struct datahead *) (data + here->packet);
405
406 if (! check_use (data, head->first_free, usemap,
407 use_data | (here->first ? use_first : 0),
408 here->packet, dh->allocsize))
409 goto fail;
410
411 if (dh->allocsize < sizeof (struct datahead)
412 || dh->recsize > dh->allocsize
413 || (dh->notfound != false && dh->notfound != true)
414 || (dh->usable != false && dh->usable != true))
415 goto fail;
416
417 if (here->key < here->packet + sizeof (struct datahead)
418 || here->key > here->packet + dh->allocsize
419 || here->key + here->len > here->packet + dh->allocsize)
420 {
421#if SEPARATE_KEY
422 /* If keys can appear outside of data, this should be done
423 instead. But gc doesn't mark the data in that case. */
424 if (! check_use (data, head->first_free, usemap,
425 use_key | (here->first ? use_first : 0),
426 here->key, here->len))
427#endif
428 goto fail;
429 }
430
431 work = here->next;
432 }
433 }
434
435 if (he_cnt != head->nentries)
436 goto fail;
437
438 /* See if all data and keys had at least one reference from
439 he->first == true hashentry. */
440 for (ref_t idx = 0; idx < head->first_free; ++idx)
441 {
442#if SEPARATE_KEY
443 if (usemap[idx] == use_key_begin)
444 goto fail;
445#endif
446 if (usemap[idx] == use_data_begin)
447 goto fail;
448 }
449
450 /* Finally, make sure the database hasn't changed since the first test. */
451 if (memcmp (mem, &head_copy, sizeof (*head)) != 0)
452 goto fail;
453
454 free (usemap);
455 return 1;
456
457fail:
458 free (usemap);
459 return 0;
460}
461
462
a334319f
UD
463/* Initialize database information structures. */
464void
465nscd_init (void)
0ecb606c 466{
057685e4
UD
467 /* Look up unprivileged uid/gid/groups before we start listening on the
468 socket */
469 if (server_user != NULL)
470 begin_drop_privileges ();
471
67479a70
UD
472 if (nthreads == -1)
473 /* No configuration for this value, assume a default. */
474 nthreads = 2 * lastdb;
d67281a7 475
d2dc7d84 476 for (size_t cnt = 0; cnt < lastdb; ++cnt)
67479a70 477 if (dbs[cnt].enabled)
9db29cde 478 {
67479a70 479 pthread_rwlock_init (&dbs[cnt].lock, NULL);
a95a08b4 480 pthread_mutex_init (&dbs[cnt].memlock, NULL);
264d5b94 481
a95a08b4 482 if (dbs[cnt].persistent)
e09edf23 483 {
a95a08b4
UD
484 /* Try to open the appropriate file on disk. */
485 int fd = open (dbs[cnt].db_filename, O_RDWR);
486 if (fd != -1)
487 {
488 struct stat64 st;
489 void *mem;
490 size_t total;
491 struct database_pers_head head;
492 ssize_t n = TEMP_FAILURE_RETRY (read (fd, &head,
493 sizeof (head)));
494 if (n != sizeof (head) || fstat64 (fd, &st) != 0)
495 {
496 fail_db:
497 dbg_log (_("invalid persistent database file \"%s\": %s"),
498 dbs[cnt].db_filename, strerror (errno));
dc4bb1c2 499 unlink (dbs[cnt].db_filename);
a95a08b4
UD
500 }
501 else if (head.module == 0 && head.data_size == 0)
502 {
503 /* The file has been created, but the head has not been
504 initialized yet. Remove the old file. */
505 unlink (dbs[cnt].db_filename);
506 }
507 else if (head.header_size != (int) sizeof (head))
508 {
509 dbg_log (_("invalid persistent database file \"%s\": %s"),
510 dbs[cnt].db_filename,
511 _("header size does not match"));
dc4bb1c2 512 unlink (dbs[cnt].db_filename);
a95a08b4
UD
513 }
514 else if ((total = (sizeof (head)
c207f23b 515 + roundup (head.module * sizeof (ref_t),
a95a08b4
UD
516 ALIGN)
517 + head.data_size))
dc4bb1c2
UD
518 > st.st_size
519 || total < sizeof (head))
a95a08b4
UD
520 {
521 dbg_log (_("invalid persistent database file \"%s\": %s"),
522 dbs[cnt].db_filename,
523 _("file size does not match"));
dc4bb1c2 524 unlink (dbs[cnt].db_filename);
a95a08b4 525 }
2c210d1e
UD
526 /* Note we map with the maximum size allowed for the
527 database. This is likely much larger than the
528 actual file size. This is OK on most OSes since
529 extensions of the underlying file will
530 automatically translate more pages available for
531 memory access. */
532 else if ((mem = mmap (NULL, dbs[cnt].max_db_size,
533 PROT_READ | PROT_WRITE,
534 MAP_SHARED, fd, 0))
535 == MAP_FAILED)
a95a08b4 536 goto fail_db;
dc4bb1c2
UD
537 else if (!verify_persistent_db (mem, &head, cnt))
538 {
539 munmap (mem, total);
540 dbg_log (_("invalid persistent database file \"%s\": %s"),
541 dbs[cnt].db_filename,
542 _("verification failed"));
543 unlink (dbs[cnt].db_filename);
544 }
a95a08b4
UD
545 else
546 {
547 /* Success. We have the database. */
548 dbs[cnt].head = mem;
549 dbs[cnt].memsize = total;
550 dbs[cnt].data = (char *)
551 &dbs[cnt].head->array[roundup (dbs[cnt].head->module,
552 ALIGN / sizeof (ref_t))];
553 dbs[cnt].mmap_used = true;
554
555 if (dbs[cnt].suggested_module > head.module)
556 dbg_log (_("suggested size of table for database %s larger than the persistent database's table"),
557 dbnames[cnt]);
558
559 dbs[cnt].wr_fd = fd;
560 fd = -1;
561 /* We also need a read-only descriptor. */
d13a3c57
UD
562 if (dbs[cnt].shared)
563 {
564 dbs[cnt].ro_fd = open (dbs[cnt].db_filename, O_RDONLY);
565 if (dbs[cnt].ro_fd == -1)
566 dbg_log (_("\
a95a08b4 567cannot create read-only descriptor for \"%s\"; no mmap"),
d13a3c57
UD
568 dbs[cnt].db_filename);
569 }
a95a08b4
UD
570
571 // XXX Shall we test whether the descriptors actually
572 // XXX point to the same file?
573 }
574
575 /* Close the file descriptors in case something went
576 wrong in which case the variable have not been
577 assigned -1. */
578 if (fd != -1)
579 close (fd);
580 }
581 }
582
583 if (dbs[cnt].head == NULL)
584 {
585 /* No database loaded. Allocate the data structure,
586 possibly on disk. */
587 struct database_pers_head head;
588 size_t total = (sizeof (head)
589 + roundup (dbs[cnt].suggested_module
590 * sizeof (ref_t), ALIGN)
591 + (dbs[cnt].suggested_module
592 * DEFAULT_DATASIZE_PER_BUCKET));
593
594 /* Try to create the database. If we do not need a
595 persistent database create a temporary file. */
596 int fd;
597 int ro_fd = -1;
598 if (dbs[cnt].persistent)
599 {
600 fd = open (dbs[cnt].db_filename,
601 O_RDWR | O_CREAT | O_EXCL | O_TRUNC,
602 S_IRUSR | S_IWUSR);
d13a3c57 603 if (fd != -1 && dbs[cnt].shared)
a95a08b4
UD
604 ro_fd = open (dbs[cnt].db_filename, O_RDONLY);
605 }
606 else
607 {
a8a58967 608 char fname[] = _PATH_NSCD_XYZ_DB_TMP;
a95a08b4
UD
609 fd = mkstemp (fname);
610
611 /* We do not need the file name anymore after we
612 opened another file descriptor in read-only mode. */
5ca3d19c 613 if (fd != -1)
a95a08b4 614 {
5ca3d19c
UD
615 if (dbs[cnt].shared)
616 ro_fd = open (fname, O_RDONLY);
a95a08b4
UD
617
618 unlink (fname);
619 }
620 }
621
622 if (fd == -1)
623 {
624 if (errno == EEXIST)
625 {
626 dbg_log (_("database for %s corrupted or simultaneously used; remove %s manually if necessary and restart"),
627 dbnames[cnt], dbs[cnt].db_filename);
628 // XXX Correct way to terminate?
629 exit (1);
630 }
631
632 if (dbs[cnt].persistent)
633 dbg_log (_("cannot create %s; no persistent database used"),
634 dbs[cnt].db_filename);
635 else
636 dbg_log (_("cannot create %s; no sharing possible"),
637 dbs[cnt].db_filename);
638
639 dbs[cnt].persistent = 0;
640 // XXX remember: no mmap
641 }
642 else
643 {
644 /* Tell the user if we could not create the read-only
645 descriptor. */
d13a3c57 646 if (ro_fd == -1 && dbs[cnt].shared)
a95a08b4
UD
647 dbg_log (_("\
648cannot create read-only descriptor for \"%s\"; no mmap"),
649 dbs[cnt].db_filename);
650
651 /* Before we create the header, initialiye the hash
652 table. So that if we get interrupted if writing
653 the header we can recognize a partially initialized
654 database. */
655 size_t ps = sysconf (_SC_PAGESIZE);
656 char tmpbuf[ps];
657 assert (~ENDREF == 0);
658 memset (tmpbuf, '\xff', ps);
659
660 size_t remaining = dbs[cnt].suggested_module * sizeof (ref_t);
661 off_t offset = sizeof (head);
662
663 size_t towrite;
664 if (offset % ps != 0)
665 {
666 towrite = MIN (remaining, ps - (offset % ps));
233399bc
UD
667 if (pwrite (fd, tmpbuf, towrite, offset) != towrite)
668 goto write_fail;
a95a08b4
UD
669 offset += towrite;
670 remaining -= towrite;
671 }
672
673 while (remaining > ps)
674 {
233399bc
UD
675 if (pwrite (fd, tmpbuf, ps, offset) == -1)
676 goto write_fail;
a95a08b4
UD
677 offset += ps;
678 remaining -= ps;
679 }
680
233399bc
UD
681 if (remaining > 0
682 && pwrite (fd, tmpbuf, remaining, offset) != remaining)
683 goto write_fail;
a95a08b4
UD
684
685 /* Create the header of the file. */
686 struct database_pers_head head =
687 {
688 .version = DB_VERSION,
689 .header_size = sizeof (head),
690 .module = dbs[cnt].suggested_module,
691 .data_size = (dbs[cnt].suggested_module
692 * DEFAULT_DATASIZE_PER_BUCKET),
693 .first_free = 0
694 };
695 void *mem;
696
697 if ((TEMP_FAILURE_RETRY (write (fd, &head, sizeof (head)))
698 != sizeof (head))
2c210d1e
UD
699 || (TEMP_FAILURE_RETRY_VAL (posix_fallocate (fd, 0, total))
700 != 0)
701 || (mem = mmap (NULL, dbs[cnt].max_db_size,
702 PROT_READ | PROT_WRITE,
a95a08b4
UD
703 MAP_SHARED, fd, 0)) == MAP_FAILED)
704 {
233399bc 705 write_fail:
a95a08b4
UD
706 unlink (dbs[cnt].db_filename);
707 dbg_log (_("cannot write to database file %s: %s"),
708 dbs[cnt].db_filename, strerror (errno));
709 dbs[cnt].persistent = 0;
710 }
711 else
712 {
713 /* Success. */
714 dbs[cnt].head = mem;
715 dbs[cnt].data = (char *)
716 &dbs[cnt].head->array[roundup (dbs[cnt].head->module,
717 ALIGN / sizeof (ref_t))];
718 dbs[cnt].memsize = total;
719 dbs[cnt].mmap_used = true;
720
721 /* Remember the descriptors. */
722 dbs[cnt].wr_fd = fd;
723 dbs[cnt].ro_fd = ro_fd;
724 fd = -1;
725 ro_fd = -1;
726 }
727
728 if (fd != -1)
729 close (fd);
730 if (ro_fd != -1)
731 close (ro_fd);
732 }
733 }
734
4401d759
UD
735 if (paranoia
736 && ((dbs[cnt].wr_fd != -1
737 && fcntl (dbs[cnt].wr_fd, F_SETFD, FD_CLOEXEC) == -1)
738 || (dbs[cnt].ro_fd != -1
739 && fcntl (dbs[cnt].ro_fd, F_SETFD, FD_CLOEXEC) == -1)))
740 {
741 dbg_log (_("\
742cannot set socket to close on exec: %s; disabling paranoia mode"),
743 strerror (errno));
744 paranoia = 0;
745 }
746
a95a08b4
UD
747 if (dbs[cnt].head == NULL)
748 {
749 /* We do not use the persistent database. Just
750 create an in-memory data structure. */
751 assert (! dbs[cnt].persistent);
752
753 dbs[cnt].head = xmalloc (sizeof (struct database_pers_head)
754 + (dbs[cnt].suggested_module
755 * sizeof (ref_t)));
25059769 756 memset (dbs[cnt].head, '\0', sizeof (struct database_pers_head));
a95a08b4
UD
757 assert (~ENDREF == 0);
758 memset (dbs[cnt].head->array, '\xff',
759 dbs[cnt].suggested_module * sizeof (ref_t));
760 dbs[cnt].head->module = dbs[cnt].suggested_module;
761 dbs[cnt].head->data_size = (DEFAULT_DATASIZE_PER_BUCKET
762 * dbs[cnt].head->module);
763 dbs[cnt].data = xmalloc (dbs[cnt].head->data_size);
764 dbs[cnt].head->first_free = 0;
c207f23b
UD
765
766 dbs[cnt].shared = 0;
767 assert (dbs[cnt].ro_fd == -1);
e09edf23 768 }
d67281a7 769
67479a70 770 if (dbs[cnt].check_file)
d67281a7 771 {
67479a70 772 /* We need the modification date of the file. */
80ea3037 773 struct stat64 st;
d67281a7 774
80ea3037 775 if (stat64 (dbs[cnt].filename, &st) < 0)
d67281a7 776 {
67479a70
UD
777 /* We cannot stat() the file, disable file checking. */
778 dbg_log (_("cannot stat() file `%s': %s"),
e09edf23 779 dbs[cnt].filename, strerror (errno));
67479a70 780 dbs[cnt].check_file = 0;
d67281a7
UD
781 }
782 else
67479a70
UD
783 dbs[cnt].file_mtime = st.st_mtime;
784 }
785 }
d67281a7
UD
786
787 /* Create the socket. */
67479a70
UD
788 sock = socket (AF_UNIX, SOCK_STREAM, 0);
789 if (sock < 0)
d67281a7 790 {
67479a70 791 dbg_log (_("cannot open socket: %s"), strerror (errno));
64d64de6 792 exit (errno == EACCES ? 4 : 1);
d67281a7
UD
793 }
794 /* Bind a name to the socket. */
d2dc7d84 795 struct sockaddr_un sock_addr;
d67281a7
UD
796 sock_addr.sun_family = AF_UNIX;
797 strcpy (sock_addr.sun_path, _PATH_NSCDSOCKET);
67479a70 798 if (bind (sock, (struct sockaddr *) &sock_addr, sizeof (sock_addr)) < 0)
d67281a7
UD
799 {
800 dbg_log ("%s: %s", _PATH_NSCDSOCKET, strerror (errno));
64d64de6 801 exit (errno == EACCES ? 4 : 1);
d67281a7 802 }
67479a70 803
4401d759 804 /* We don't want to get stuck on accept. */
d6db0975 805 int fl = fcntl (sock, F_GETFL);
4401d759
UD
806 if (fl == -1 || fcntl (sock, F_SETFL, fl | O_NONBLOCK) == -1)
807 {
808 dbg_log (_("cannot change socket to nonblocking mode: %s"),
809 strerror (errno));
810 exit (1);
811 }
812
813 /* The descriptor needs to be closed on exec. */
814 if (paranoia && fcntl (sock, F_SETFD, FD_CLOEXEC) == -1)
815 {
816 dbg_log (_("cannot set socket to close on exec: %s"),
817 strerror (errno));
818 exit (1);
819 }
d6db0975 820
d67281a7 821 /* Set permissions for the socket. */
a95a08b4 822 chmod (_PATH_NSCDSOCKET, DEFFILEMODE);
d67281a7
UD
823
824 /* Set the socket up to accept connections. */
67479a70 825 if (listen (sock, SOMAXCONN) < 0)
d67281a7 826 {
67479a70
UD
827 dbg_log (_("cannot enable socket to accept connections: %s"),
828 strerror (errno));
d67281a7
UD
829 exit (1);
830 }
057685e4
UD
831
832 /* Change to unprivileged uid/gid/groups if specifed in config file */
833 if (server_user != NULL)
834 finish_drop_privileges ();
d67281a7
UD
835}
836
67479a70
UD
837
838/* Close the connections. */
d67281a7 839void
67479a70 840close_sockets (void)
d67281a7 841{
67479a70
UD
842 close (sock);
843}
d67281a7 844
a12ce44f 845
756409c4 846static void
902c4291 847invalidate_cache (char *key, int fd)
756409c4
UD
848{
849 dbtype number;
902c4291 850 int32_t resp;
756409c4 851
b21fa963
UD
852 for (number = pwddb; number < lastdb; ++number)
853 if (strcmp (key, dbnames[number]) == 0)
854 {
855 if (dbs[number].reset_res)
856 res_init ();
482bbeb9 857
b21fa963
UD
858 break;
859 }
860
861 if (number == lastdb)
902c4291
UD
862 {
863 resp = EINVAL;
864 writeall (fd, &resp, sizeof (resp));
865 return;
866 }
756409c4 867
fd665070 868 if (dbs[number].enabled)
902c4291
UD
869 prune_cache (&dbs[number], LONG_MAX, fd);
870 else
871 {
872 resp = 0;
873 writeall (fd, &resp, sizeof (resp));
874 }
756409c4
UD
875}
876
67479a70 877
c207f23b
UD
878#ifdef SCM_RIGHTS
879static void
880send_ro_fd (struct database_dyn *db, char *key, int fd)
881{
882 /* If we do not have an read-only file descriptor do nothing. */
883 if (db->ro_fd == -1)
884 return;
885
886 /* We need to send some data along with the descriptor. */
887 struct iovec iov[1];
888 iov[0].iov_base = key;
889 iov[0].iov_len = strlen (key) + 1;
890
891 /* Prepare the control message to transfer the descriptor. */
a08ab897
UD
892 union
893 {
894 struct cmsghdr hdr;
895 char bytes[CMSG_SPACE (sizeof (int))];
896 } buf;
c207f23b 897 struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1,
a08ab897
UD
898 .msg_control = buf.bytes,
899 .msg_controllen = sizeof (buf) };
c207f23b
UD
900 struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
901
902 cmsg->cmsg_level = SOL_SOCKET;
903 cmsg->cmsg_type = SCM_RIGHTS;
904 cmsg->cmsg_len = CMSG_LEN (sizeof (int));
905
906 *(int *) CMSG_DATA (cmsg) = db->ro_fd;
907
908 msg.msg_controllen = cmsg->cmsg_len;
909
910 /* Send the control message. We repeat when we are interrupted but
911 everything else is ignored. */
6925ef9a
UD
912#ifndef MSG_NOSIGNAL
913# define MSG_NOSIGNAL 0
914#endif
915 (void) TEMP_FAILURE_RETRY (sendmsg (fd, &msg, MSG_NOSIGNAL));
c207f23b
UD
916
917 if (__builtin_expect (debug_level > 0, 0))
918 dbg_log (_("provide access to FD %d, for %s"), db->ro_fd, key);
919}
920#endif /* SCM_RIGHTS */
921
922
67479a70
UD
923/* Handle new request. */
924static void
a1c542bf 925handle_request (int fd, request_header *req, void *key, uid_t uid)
67479a70 926{
23700036 927 if (__builtin_expect (req->version, NSCD_VERSION) != NSCD_VERSION)
d67281a7 928 {
98e75a1c
UD
929 if (debug_level > 0)
930 dbg_log (_("\
67479a70 931cannot handle old request version %d; current version is %d"),
98e75a1c 932 req->version, NSCD_VERSION);
d67281a7
UD
933 return;
934 }
935
74a30a58
UD
936 /* Make the SELinux check before we go on to the standard checks. We
937 need to verify that the request type is valid, since it has not
938 yet been checked at this point. */
939 if (selinux_enabled
43397eaf
UD
940 && __builtin_expect (req->type >= GETPWBYNAME, 1)
941 && __builtin_expect (req->type < LASTREQ, 1)
74a30a58
UD
942 && nscd_request_avc_has_perm (fd, req->type) != 0)
943 return;
944
a95a08b4
UD
945 struct database_dyn *db = serv2db[req->type];
946
f7e7a396
UD
947 // XXX Clean up so that each new command need not introduce a
948 // XXX new conditional.
d19687d6 949 if ((__builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
b21fa963
UD
950 && __builtin_expect (req->type, GETHOSTBYADDRv6) <= GETHOSTBYADDRv6)
951 || req->type == GETAI || req->type == INITGROUPS
952 || req->type == GETSERVBYNAME || req->type == GETSERVBYPORT)
d67281a7 953 {
23700036 954 if (__builtin_expect (debug_level, 0) > 0)
8d8c6efa
UD
955 {
956 if (req->type == GETHOSTBYADDR || req->type == GETHOSTBYADDRv6)
957 {
958 char buf[INET6_ADDRSTRLEN];
959
960 dbg_log ("\t%s (%s)", serv2str[req->type],
961 inet_ntop (req->type == GETHOSTBYADDR
962 ? AF_INET : AF_INET6,
963 key, buf, sizeof (buf)));
964 }
965 else
a95a08b4 966 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
8d8c6efa 967 }
d67281a7 968
67479a70
UD
969 /* Is this service enabled? */
970 if (!db->enabled)
971 {
ce85d65b 972 /* No, sent the prepared record. */
2c210d1e
UD
973 if (TEMP_FAILURE_RETRY (send (fd, db->disabled_iov->iov_base,
974 db->disabled_iov->iov_len,
975 MSG_NOSIGNAL))
4c5dd2a2 976 != (ssize_t) db->disabled_iov->iov_len
23700036 977 && __builtin_expect (debug_level, 0) > 0)
67479a70
UD
978 {
979 /* We have problems sending the result. */
980 char buf[256];
981 dbg_log (_("cannot write result: %s"),
982 strerror_r (errno, buf, sizeof (buf)));
983 }
d67281a7 984
67479a70
UD
985 return;
986 }
d67281a7 987
67479a70 988 /* Be sure we can read the data. */
c86e6aec
UD
989 if (__builtin_expect (pthread_rwlock_tryrdlock (&db->lock) != 0, 0))
990 {
a95a08b4 991 ++db->head->rdlockdelayed;
c86e6aec
UD
992 pthread_rwlock_rdlock (&db->lock);
993 }
67479a70
UD
994
995 /* See whether we can handle it from the cache. */
a95a08b4
UD
996 struct datahead *cached;
997 cached = (struct datahead *) cache_search (req->type, key, req->key_len,
998 db, uid);
67479a70
UD
999 if (cached != NULL)
1000 {
1001 /* Hurray it's in the cache. */
eac10791
UD
1002 ssize_t nwritten;
1003
1004#ifdef HAVE_SENDFILE
1005 if (db->mmap_used || !cached->notfound)
1006 {
1007 assert (db->wr_fd != -1);
1008 assert ((char *) cached->data > (char *) db->data);
1009 assert ((char *) cached->data - (char *) db->head
1010 + cached->recsize
1011 <= (sizeof (struct database_pers_head)
1012 + db->head->module * sizeof (ref_t)
1013 + db->head->data_size));
bd547139
UD
1014 nwritten = sendfileall (fd, db->wr_fd,
1015 (char *) cached->data
1016 - (char *) db->head, cached->recsize);
eac10791
UD
1017# ifndef __ASSUME_SENDFILE
1018 if (nwritten == -1 && errno == ENOSYS)
1019 goto use_write;
1020# endif
1021 }
1022 else
1023# ifndef __ASSUME_SENDFILE
1024 use_write:
1025# endif
1026#endif
1027 nwritten = writeall (fd, cached->data, cached->recsize);
1028
1029 if (nwritten != cached->recsize
23700036 1030 && __builtin_expect (debug_level, 0) > 0)
67479a70
UD
1031 {
1032 /* We have problems sending the result. */
1033 char buf[256];
1034 dbg_log (_("cannot write result: %s"),
1035 strerror_r (errno, buf, sizeof (buf)));
1036 }
1037
1038 pthread_rwlock_unlock (&db->lock);
1039
1040 return;
1041 }
1042
1043 pthread_rwlock_unlock (&db->lock);
d67281a7 1044 }
23700036 1045 else if (__builtin_expect (debug_level, 0) > 0)
756409c4
UD
1046 {
1047 if (req->type == INVALIDATE)
c207f23b 1048 dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
0532e21b 1049 else
a95a08b4 1050 dbg_log ("\t%s", serv2str[req->type]);
756409c4 1051 }
67479a70
UD
1052
1053 /* Handle the request. */
1054 switch (req->type)
d67281a7 1055 {
67479a70 1056 case GETPWBYNAME:
a95a08b4 1057 addpwbyname (db, fd, req, key, uid);
67479a70
UD
1058 break;
1059
1060 case GETPWBYUID:
a95a08b4 1061 addpwbyuid (db, fd, req, key, uid);
67479a70
UD
1062 break;
1063
1064 case GETGRBYNAME:
a95a08b4 1065 addgrbyname (db, fd, req, key, uid);
67479a70
UD
1066 break;
1067
1068 case GETGRBYGID:
a95a08b4 1069 addgrbygid (db, fd, req, key, uid);
67479a70
UD
1070 break;
1071
1072 case GETHOSTBYNAME:
a95a08b4 1073 addhstbyname (db, fd, req, key, uid);
67479a70
UD
1074 break;
1075
1076 case GETHOSTBYNAMEv6:
a95a08b4 1077 addhstbynamev6 (db, fd, req, key, uid);
67479a70
UD
1078 break;
1079
1080 case GETHOSTBYADDR:
a95a08b4 1081 addhstbyaddr (db, fd, req, key, uid);
67479a70
UD
1082 break;
1083
1084 case GETHOSTBYADDRv6:
a95a08b4 1085 addhstbyaddrv6 (db, fd, req, key, uid);
67479a70
UD
1086 break;
1087
d19687d6
UD
1088 case GETAI:
1089 addhstai (db, fd, req, key, uid);
1090 break;
1091
f7e7a396
UD
1092 case INITGROUPS:
1093 addinitgroups (db, fd, req, key, uid);
1094 break;
1095
b21fa963
UD
1096 case GETSERVBYNAME:
1097 addservbyname (db, fd, req, key, uid);
1098 break;
1099
1100 case GETSERVBYPORT:
1101 addservbyport (db, fd, req, key, uid);
1102 break;
1103
67479a70 1104 case GETSTAT:
67479a70 1105 case SHUTDOWN:
756409c4 1106 case INVALIDATE:
70e2ebba
UD
1107 {
1108 /* Get the callers credentials. */
cedc8559 1109#ifdef SO_PEERCRED
70e2ebba
UD
1110 struct ucred caller;
1111 socklen_t optlen = sizeof (caller);
be3c40b6 1112
70e2ebba
UD
1113 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
1114 {
1115 char buf[256];
a1c542bf 1116
c69136ae 1117 dbg_log (_("error getting caller's id: %s"),
70e2ebba
UD
1118 strerror_r (errno, buf, sizeof (buf)));
1119 break;
1120 }
a12ce44f 1121
70e2ebba 1122 uid = caller.uid;
a12ce44f 1123#else
70e2ebba
UD
1124 /* Some systems have no SO_PEERCRED implementation. They don't
1125 care about security so we don't as well. */
1126 uid = 0;
cedc8559 1127#endif
70e2ebba 1128 }
a12ce44f
UD
1129
1130 /* Accept shutdown, getstat and invalidate only from root. For
1131 the stat call also allow the user specified in the config file. */
1132 if (req->type == GETSTAT)
1133 {
1134 if (uid == 0 || uid == stat_uid)
1135 send_stats (fd, dbs);
1136 }
1137 else if (uid == 0)
1138 {
1139 if (req->type == INVALIDATE)
902c4291 1140 invalidate_cache (key, fd);
a12ce44f
UD
1141 else
1142 termination_handler (0);
a1c542bf 1143 }
67479a70
UD
1144 break;
1145
c207f23b
UD
1146 case GETFDPW:
1147 case GETFDGR:
1148 case GETFDHST:
b21fa963 1149 case GETFDSERV:
c207f23b
UD
1150#ifdef SCM_RIGHTS
1151 send_ro_fd (serv2db[req->type], key, fd);
1152#endif
1153 break;
1154
67479a70 1155 default:
64acf8ed
UD
1156 /* Ignore the command, it's nothing we know. */
1157 break;
d67281a7 1158 }
67479a70
UD
1159}
1160
d67281a7 1161
4401d759
UD
1162/* Restart the process. */
1163static void
1164restart (void)
1165{
1166 /* First determine the parameters. We do not use the parameters
1167 passed to main() since in case nscd is started by running the
1168 dynamic linker this will not work. Yes, this is not the usual
1169 case but nscd is part of glibc and we occasionally do this. */
1170 size_t buflen = 1024;
1171 char *buf = alloca (buflen);
1172 size_t readlen = 0;
1173 int fd = open ("/proc/self/cmdline", O_RDONLY);
1174 if (fd == -1)
1175 {
1176 dbg_log (_("\
1177cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
1178 strerror (errno));
1179
1180 paranoia = 0;
1181 return;
1182 }
1183
1184 while (1)
1185 {
1186 ssize_t n = TEMP_FAILURE_RETRY (read (fd, buf + readlen,
1187 buflen - readlen));
1188 if (n == -1)
1189 {
1190 dbg_log (_("\
b21fa963 1191cannot read /proc/self/cmdline: %s; disabling paranoia mode"),
4401d759
UD
1192 strerror (errno));
1193
1194 close (fd);
1195 paranoia = 0;
1196 return;
1197 }
1198
1199 readlen += n;
1200
1201 if (readlen < buflen)
1202 break;
1203
1204 /* We might have to extend the buffer. */
1205 size_t old_buflen = buflen;
1206 char *newp = extend_alloca (buf, buflen, 2 * buflen);
1207 buf = memmove (newp, buf, old_buflen);
1208 }
1209
1210 close (fd);
1211
1212 /* Parse the command line. Worst case scenario: every two
1213 characters form one parameter (one character plus NUL). */
1214 char **argv = alloca ((readlen / 2 + 1) * sizeof (argv[0]));
1215 int argc = 0;
1216
1217 char *cp = buf;
1218 while (cp < buf + readlen)
1219 {
1220 argv[argc++] = cp;
1221 cp = (char *) rawmemchr (cp, '\0') + 1;
1222 }
1223 argv[argc] = NULL;
1224
1225 /* Second, change back to the old user if we changed it. */
1226 if (server_user != NULL)
1227 {
464c9fad 1228 if (setresuid (old_uid, old_uid, old_uid) != 0)
4401d759
UD
1229 {
1230 dbg_log (_("\
1231cannot change to old UID: %s; disabling paranoia mode"),
1232 strerror (errno));
1233
1234 paranoia = 0;
1235 return;
1236 }
1237
464c9fad 1238 if (setresgid (old_gid, old_gid, old_gid) != 0)
4401d759
UD
1239 {
1240 dbg_log (_("\
1241cannot change to old GID: %s; disabling paranoia mode"),
1242 strerror (errno));
1243
1244 setuid (server_uid);
1245 paranoia = 0;
1246 return;
1247 }
1248 }
1249
1250 /* Next change back to the old working directory. */
1251 if (chdir (oldcwd) == -1)
1252 {
1253 dbg_log (_("\
1254cannot change to old working directory: %s; disabling paranoia mode"),
1255 strerror (errno));
1256
1257 if (server_user != NULL)
1258 {
1259 setuid (server_uid);
1260 setgid (server_gid);
1261 }
1262 paranoia = 0;
1263 return;
1264 }
1265
1266 /* Synchronize memory. */
1267 for (int cnt = 0; cnt < lastdb; ++cnt)
1268 {
1269 /* Make sure nobody keeps using the database. */
1270 dbs[cnt].head->timestamp = 0;
1271
1272 if (dbs[cnt].persistent)
1273 // XXX async OK?
1274 msync (dbs[cnt].head, dbs[cnt].memsize, MS_ASYNC);
1275 }
1276
1277 /* The preparations are done. */
1278 execv ("/proc/self/exe", argv);
1279
1280 /* If we come here, we will never be able to re-exec. */
1281 dbg_log (_("re-exec failed: %s; disabling paranoia mode"),
1282 strerror (errno));
1283
1284 if (server_user != NULL)
1285 {
1286 setuid (server_uid);
1287 setgid (server_gid);
1288 }
233399bc
UD
1289 if (chdir ("/") != 0)
1290 dbg_log (_("cannot change current working directory to \"/\": %s"),
1291 strerror (errno));
4401d759
UD
1292 paranoia = 0;
1293}
1294
1295
1945c96f
UD
1296/* List of file descriptors. */
1297struct fdlist
1298{
1299 int fd;
1300 struct fdlist *next;
1301};
1302/* Memory allocated for the list. */
1303static struct fdlist *fdlist;
1304/* List of currently ready-to-read file descriptors. */
1305static struct fdlist *readylist;
1306
1307/* Conditional variable and mutex to signal availability of entries in
1308 READYLIST. The condvar is initialized dynamically since we might
1309 use a different clock depending on availability. */
1310static pthread_cond_t readylist_cond;
1311static pthread_mutex_t readylist_lock = PTHREAD_MUTEX_INITIALIZER;
1312
1313/* The clock to use with the condvar. */
1314static clockid_t timeout_clock = CLOCK_REALTIME;
1315
1316/* Number of threads ready to handle the READYLIST. */
1317static unsigned long int nready;
1318
1319
67479a70
UD
1320/* This is the main loop. It is replicated in different threads but the
1321 `poll' call makes sure only one thread handles an incoming connection. */
1322static void *
1323__attribute__ ((__noreturn__))
1324nscd_run (void *p)
1325{
1945c96f
UD
1326 const long int my_number = (long int) p;
1327 const int run_prune = my_number < lastdb && dbs[my_number].enabled;
1328 struct timespec prune_ts;
1329 int to = 0;
1330 char buf[256];
264d5b94 1331
72ae1e97 1332 if (run_prune)
1945c96f
UD
1333 {
1334 setup_thread (&dbs[my_number]);
081fc592 1335
1945c96f
UD
1336 /* We are running. */
1337 dbs[my_number].head->timestamp = time (NULL);
d67281a7 1338
1945c96f
UD
1339 if (clock_gettime (timeout_clock, &prune_ts) == -1)
1340 /* Should never happen. */
1341 abort ();
0fdb4f42 1342
1945c96f
UD
1343 /* Compute timeout time. */
1344 prune_ts.tv_sec += CACHE_PRUNE_INTERVAL;
1345 }
1346
1347 /* Initial locking. */
1348 pthread_mutex_lock (&readylist_lock);
1349
1350 /* One more thread available. */
1351 ++nready;
0fdb4f42 1352
1945c96f
UD
1353 while (1)
1354 {
1355 while (readylist == NULL)
d6db0975 1356 {
d6db0975
UD
1357 if (run_prune)
1358 {
1945c96f
UD
1359 /* Wait, but not forever. */
1360 to = pthread_cond_timedwait (&readylist_cond, &readylist_lock,
1361 &prune_ts);
1362
1363 /* If we were woken and there is no work to be done,
1364 just start pruning. */
1365 if (readylist == NULL && to == ETIMEDOUT)
1366 {
4401d759 1367 --nready;
1945c96f
UD
1368 pthread_mutex_unlock (&readylist_lock);
1369 goto only_prune;
1370 }
d6db0975 1371 }
1945c96f
UD
1372 else
1373 /* No need to timeout. */
1374 pthread_cond_wait (&readylist_cond, &readylist_lock);
1375 }
0fdb4f42 1376
1945c96f
UD
1377 struct fdlist *it = readylist->next;
1378 if (readylist->next == readylist)
1379 /* Just one entry on the list. */
1380 readylist = NULL;
1381 else
1382 readylist->next = it->next;
0fdb4f42 1383
1945c96f
UD
1384 /* Extract the information and mark the record ready to be used
1385 again. */
1386 int fd = it->fd;
1387 it->next = NULL;
0fdb4f42 1388
1945c96f
UD
1389 /* One more thread available. */
1390 --nready;
67479a70 1391
1945c96f
UD
1392 /* We are done with the list. */
1393 pthread_mutex_unlock (&readylist_lock);
67479a70 1394
1945c96f
UD
1395 /* We do not want to block on a short read or so. */
1396 int fl = fcntl (fd, F_GETFL);
1397 if (fl == -1 || fcntl (fd, F_SETFL, fl | O_NONBLOCK) == -1)
1398 goto close_and_out;
0fdb4f42
UD
1399
1400 /* Now read the request. */
1945c96f 1401 request_header req;
0fdb4f42
UD
1402 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, &req, sizeof (req)))
1403 != sizeof (req), 0))
d67281a7 1404 {
1945c96f
UD
1405 /* We failed to read data. Note that this also might mean we
1406 failed because we would have blocked. */
0fdb4f42
UD
1407 if (debug_level > 0)
1408 dbg_log (_("short read while reading request: %s"),
1409 strerror_r (errno, buf, sizeof (buf)));
1945c96f 1410 goto close_and_out;
0fdb4f42
UD
1411 }
1412
3c82c131
UD
1413 /* Check whether this is a valid request type. */
1414 if (req.type < GETPWBYNAME || req.type >= LASTREQ)
1415 goto close_and_out;
1416
0fdb4f42
UD
1417 /* Some systems have no SO_PEERCRED implementation. They don't
1418 care about security so we don't as well. */
1945c96f 1419 uid_t uid = -1;
c86e6aec 1420#ifdef SO_PEERCRED
1945c96f
UD
1421 pid_t pid = 0;
1422
70e2ebba 1423 if (__builtin_expect (debug_level > 0, 0))
0fdb4f42
UD
1424 {
1425 struct ucred caller;
1426 socklen_t optlen = sizeof (caller);
c86e6aec 1427
0fdb4f42
UD
1428 if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) == 0)
1429 pid = caller.pid;
1430 }
cedc8559 1431#endif
a1c542bf 1432
0fdb4f42
UD
1433 /* It should not be possible to crash the nscd with a silly
1434 request (i.e., a terribly large key). We limit the size to 1kb. */
1945c96f 1435#define MAXKEYLEN 1024
0fdb4f42 1436 if (__builtin_expect (req.key_len, 1) < 0
1945c96f 1437 || __builtin_expect (req.key_len, 1) > MAXKEYLEN)
0fdb4f42
UD
1438 {
1439 if (debug_level > 0)
1440 dbg_log (_("key length in request too long: %d"), req.key_len);
0fdb4f42
UD
1441 }
1442 else
1443 {
1444 /* Get the key. */
1945c96f 1445 char keybuf[MAXKEYLEN];
0fdb4f42
UD
1446
1447 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, keybuf,
1448 req.key_len))
1449 != req.key_len, 0))
67479a70 1450 {
1945c96f 1451 /* Again, this can also mean we would have blocked. */
98e75a1c 1452 if (debug_level > 0)
0fdb4f42
UD
1453 dbg_log (_("short read while reading request key: %s"),
1454 strerror_r (errno, buf, sizeof (buf)));
1945c96f 1455 goto close_and_out;
67479a70 1456 }
0fdb4f42
UD
1457
1458 if (__builtin_expect (debug_level, 0) > 0)
67479a70 1459 {
c86e6aec 1460#ifdef SO_PEERCRED
0fdb4f42
UD
1461 if (pid != 0)
1462 dbg_log (_("\
c86e6aec 1463handle_request: request received (Version = %d) from PID %ld"),
0fdb4f42
UD
1464 req.version, (long int) pid);
1465 else
c86e6aec 1466#endif
0fdb4f42 1467 dbg_log (_("\
c86e6aec 1468handle_request: request received (Version = %d)"), req.version);
0fdb4f42 1469 }
c86e6aec 1470
0fdb4f42
UD
1471 /* Phew, we got all the data, now process it. */
1472 handle_request (fd, &req, keybuf, uid);
d67281a7 1473 }
264d5b94 1474
3c82c131
UD
1475 close_and_out:
1476 /* We are done. */
1477 close (fd);
1478
1945c96f
UD
1479 /* Check whether we should be pruning the cache. */
1480 assert (run_prune || to == 0);
1481 if (to == ETIMEDOUT)
1482 {
1483 only_prune:
1484 /* The pthread_cond_timedwait() call timed out. It is time
1485 to clean up the cache. */
1486 assert (my_number < lastdb);
902c4291 1487 prune_cache (&dbs[my_number], time (NULL), -1);
1945c96f
UD
1488
1489 if (clock_gettime (timeout_clock, &prune_ts) == -1)
1490 /* Should never happen. */
1491 abort ();
1492
1493 /* Compute next timeout time. */
1494 prune_ts.tv_sec += CACHE_PRUNE_INTERVAL;
1495
1496 /* In case the list is emtpy we do not want to run the prune
1497 code right away again. */
1498 to = 0;
1499 }
1500
1501 /* Re-locking. */
1502 pthread_mutex_lock (&readylist_lock);
1503
1504 /* One more thread available. */
1505 ++nready;
1506 }
1507}
1508
1509
fc03df7a
UD
1510static unsigned int nconns;
1511
1945c96f 1512static void
fc03df7a 1513fd_ready (int fd)
1945c96f 1514{
fc03df7a
UD
1515 pthread_mutex_lock (&readylist_lock);
1516
1517 /* Find an empty entry in FDLIST. */
1518 size_t inner;
1519 for (inner = 0; inner < nconns; ++inner)
1520 if (fdlist[inner].next == NULL)
1521 break;
1522 assert (inner < nconns);
1523
1524 fdlist[inner].fd = fd;
1525
1526 if (readylist == NULL)
1527 readylist = fdlist[inner].next = &fdlist[inner];
1945c96f 1528 else
fc03df7a
UD
1529 {
1530 fdlist[inner].next = readylist->next;
1531 readylist = readylist->next = &fdlist[inner];
1532 }
1533
1534 bool do_signal = true;
1535 if (__builtin_expect (nready == 0, 0))
1536 {
1537 ++client_queued;
1538 do_signal = false;
27e82856
UD
1539
1540 /* Try to start another thread to help out. */
1541 pthread_t th;
1542 if (nthreads < max_nthreads
1543 && pthread_create (&th, &attr, nscd_run,
1544 (void *) (long int) nthreads) == 0)
1545 {
1546 /* We got another thread. */
1547 ++nthreads;
908c9e87 1548 /* The new thread might need a kick. */
27e82856
UD
1549 do_signal = true;
1550 }
1551
fc03df7a
UD
1552 }
1553
1554 pthread_mutex_unlock (&readylist_lock);
1555
1556 /* Tell one of the worker threads there is work to do. */
1557 if (do_signal)
1558 pthread_cond_signal (&readylist_cond);
1559}
1945c96f 1560
fc03df7a 1561
4401d759
UD
1562/* Check whether restarting should happen. */
1563static inline int
1564restart_p (time_t now)
1565{
1566 return (paranoia && readylist == NULL && nready == nthreads
1567 && now >= restart_time);
1568}
1569
1570
1571/* Array for times a connection was accepted. */
fc03df7a
UD
1572static time_t *starttime;
1573
1574
1575static void
1576__attribute__ ((__noreturn__))
1577main_loop_poll (void)
1578{
1945c96f
UD
1579 struct pollfd *conns = (struct pollfd *) xmalloc (nconns
1580 * sizeof (conns[0]));
1581
1945c96f
UD
1582 conns[0].fd = sock;
1583 conns[0].events = POLLRDNORM;
1584 size_t nused = 1;
1585 size_t firstfree = 1;
1586
1587 while (1)
1588 {
1589 /* Wait for any event. We wait at most a couple of seconds so
1590 that we can check whether we should close any of the accepted
1591 connections since we have not received a request. */
1592#define MAX_ACCEPT_TIMEOUT 30
1593#define MIN_ACCEPT_TIMEOUT 5
1594#define MAIN_THREAD_TIMEOUT \
1595 (MAX_ACCEPT_TIMEOUT * 1000 \
1596 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * 1000 * nused) / (2 * nconns))
1597
1598 int n = poll (conns, nused, MAIN_THREAD_TIMEOUT);
1599
1600 time_t now = time (NULL);
1601
1602 /* If there is a descriptor ready for reading or there is a new
1603 connection, process this now. */
1604 if (n > 0)
67479a70 1605 {
1945c96f
UD
1606 if (conns[0].revents != 0)
1607 {
1608 /* We have a new incoming connection. Accept the connection. */
1609 int fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
1610
9388dcbb
UD
1611 /* Use the descriptor if we have not reached the limit. */
1612 if (fd >= 0)
1945c96f 1613 {
9388dcbb
UD
1614 if (firstfree < nconns)
1615 {
1616 conns[firstfree].fd = fd;
1617 conns[firstfree].events = POLLRDNORM;
1618 starttime[firstfree] = now;
1619 if (firstfree >= nused)
1620 nused = firstfree + 1;
1621
1622 do
1623 ++firstfree;
1624 while (firstfree < nused && conns[firstfree].fd != -1);
1625 }
1626 else
1627 /* We cannot use the connection so close it. */
1628 close (fd);
1945c96f
UD
1629 }
1630
1945c96f
UD
1631 --n;
1632 }
1633
1634 for (size_t cnt = 1; cnt < nused && n > 0; ++cnt)
1635 if (conns[cnt].revents != 0)
1636 {
fc03df7a 1637 fd_ready (conns[cnt].fd);
1945c96f
UD
1638
1639 /* Clean up the CONNS array. */
1640 conns[cnt].fd = -1;
1641 if (cnt < firstfree)
1642 firstfree = cnt;
1643 if (cnt == nused - 1)
1644 do
1645 --nused;
1646 while (conns[nused - 1].fd == -1);
1647
1648 --n;
1649 }
1650 }
1651
1652 /* Now find entries which have timed out. */
1653 assert (nused > 0);
fc03df7a
UD
1654
1655 /* We make the timeout length depend on the number of file
1656 descriptors currently used. */
1945c96f
UD
1657#define ACCEPT_TIMEOUT \
1658 (MAX_ACCEPT_TIMEOUT \
1659 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * nused) / nconns)
fc03df7a 1660 time_t laststart = now - ACCEPT_TIMEOUT;
1945c96f 1661
fc03df7a
UD
1662 for (size_t cnt = nused - 1; cnt > 0; --cnt)
1663 {
1945c96f
UD
1664 if (conns[cnt].fd != -1 && starttime[cnt] < laststart)
1665 {
1666 /* Remove the entry, it timed out. */
1667 (void) close (conns[cnt].fd);
1668 conns[cnt].fd = -1;
1669
1670 if (cnt < firstfree)
1671 firstfree = cnt;
1672 if (cnt == nused - 1)
1673 do
1674 --nused;
1675 while (conns[nused - 1].fd == -1);
1676 }
67479a70 1677 }
4401d759
UD
1678
1679 if (restart_p (now))
1680 restart ();
67308730 1681 }
d67281a7
UD
1682}
1683
67479a70 1684
fc03df7a
UD
1685#ifdef HAVE_EPOLL
1686static void
1687main_loop_epoll (int efd)
1688{
1689 struct epoll_event ev = { 0, };
1690 int nused = 1;
1691 size_t highest = 0;
1692
1693 /* Add the socket. */
1694 ev.events = EPOLLRDNORM;
1695 ev.data.fd = sock;
1696 if (epoll_ctl (efd, EPOLL_CTL_ADD, sock, &ev) == -1)
1697 /* We cannot use epoll. */
1698 return;
1699
1700 while (1)
1701 {
1702 struct epoll_event revs[100];
1703# define nrevs (sizeof (revs) / sizeof (revs[0]))
1704
1705 int n = epoll_wait (efd, revs, nrevs, MAIN_THREAD_TIMEOUT);
1706
1707 time_t now = time (NULL);
1708
1709 for (int cnt = 0; cnt < n; ++cnt)
1710 if (revs[cnt].data.fd == sock)
1711 {
1712 /* A new connection. */
1713 int fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
1714
1715 if (fd >= 0)
1716 {
1717 /* Try to add the new descriptor. */
1718 ev.data.fd = fd;
1719 if (fd >= nconns
1720 || epoll_ctl (efd, EPOLL_CTL_ADD, fd, &ev) == -1)
1721 /* The descriptor is too large or something went
1722 wrong. Close the descriptor. */
1723 close (fd);
1724 else
1725 {
1726 /* Remember when we accepted the connection. */
1727 starttime[fd] = now;
1728
1729 if (fd > highest)
1730 highest = fd;
1731
1732 ++nused;
1733 }
1734 }
1735 }
1736 else
1737 {
1738 /* Remove the descriptor from the epoll descriptor. */
908c9e87 1739 (void) epoll_ctl (efd, EPOLL_CTL_DEL, revs[cnt].data.fd, NULL);
fc03df7a 1740
2461e3dc 1741 /* Get a worker to handle the request. */
fc03df7a
UD
1742 fd_ready (revs[cnt].data.fd);
1743
1744 /* Reset the time. */
1745 starttime[revs[cnt].data.fd] = 0;
1746 if (revs[cnt].data.fd == highest)
1747 do
1748 --highest;
1749 while (highest > 0 && starttime[highest] == 0);
1750
1751 --nused;
1752 }
1753
1754 /* Now look for descriptors for accepted connections which have
1755 no reply in too long of a time. */
1756 time_t laststart = now - ACCEPT_TIMEOUT;
1757 for (int cnt = highest; cnt > STDERR_FILENO; --cnt)
1758 if (cnt != sock && starttime[cnt] != 0 && starttime[cnt] < laststart)
1759 {
1760 /* We are waiting for this one for too long. Close it. */
908c9e87 1761 (void) epoll_ctl (efd, EPOLL_CTL_DEL, cnt, NULL);
fc03df7a
UD
1762
1763 (void) close (cnt);
1764
1765 starttime[cnt] = 0;
1766 if (cnt == highest)
1767 --highest;
1768 }
1769 else if (cnt != sock && starttime[cnt] == 0 && cnt == highest)
1770 --highest;
4401d759
UD
1771
1772 if (restart_p (now))
1773 restart ();
fc03df7a
UD
1774 }
1775}
1776#endif
1777
1778
67479a70 1779/* Start all the threads we want. The initial process is thread no. 1. */
d67281a7 1780void
67479a70 1781start_threads (void)
d67281a7 1782{
1945c96f
UD
1783 /* Initialize the conditional variable we will use. The only
1784 non-standard attribute we might use is the clock selection. */
1785 pthread_condattr_t condattr;
1786 pthread_condattr_init (&condattr);
1787
3078cba2
UD
1788#if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0 \
1789 && defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
1945c96f
UD
1790 /* Determine whether the monotonous clock is available. */
1791 struct timespec dummy;
3078cba2 1792# if _POSIX_MONOTONIC_CLOCK == 0
94d824f9 1793 if (sysconf (_SC_MONOTONIC_CLOCK) > 0)
3078cba2
UD
1794# endif
1795# if _POSIX_CLOCK_SELECTION == 0
94d824f9 1796 if (sysconf (_SC_CLOCK_SELECTION) > 0)
3078cba2 1797# endif
94d824f9
UD
1798 if (clock_getres (CLOCK_MONOTONIC, &dummy) == 0
1799 && pthread_condattr_setclock (&condattr, CLOCK_MONOTONIC) == 0)
1800 timeout_clock = CLOCK_MONOTONIC;
1945c96f 1801#endif
d67281a7 1802
1945c96f
UD
1803 pthread_cond_init (&readylist_cond, &condattr);
1804 pthread_condattr_destroy (&condattr);
1805
1806
1807 /* Create the attribute for the threads. They are all created
1808 detached. */
67479a70
UD
1809 pthread_attr_init (&attr);
1810 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
27e82856
UD
1811 /* Use 1MB stacks, twice as much for 64-bit architectures. */
1812 pthread_attr_setstacksize (&attr, 1024 * 1024 * (sizeof (void *) / 4));
d67281a7 1813
67479a70
UD
1814 /* We allow less than LASTDB threads only for debugging. */
1815 if (debug_level == 0)
1816 nthreads = MAX (nthreads, lastdb);
d67281a7 1817
27e82856 1818 int nfailed = 0;
1945c96f
UD
1819 for (long int i = 0; i < nthreads; ++i)
1820 {
1821 pthread_t th;
27e82856
UD
1822 if (pthread_create (&th, &attr, nscd_run, (void *) (i - nfailed)) != 0)
1823 ++nfailed;
1824 }
1825 if (nthreads - nfailed < lastdb)
1826 {
1827 /* We could not start enough threads. */
1828 dbg_log (_("could only start %d threads; terminating"),
1829 nthreads - nfailed);
1830 exit (1);
1945c96f 1831 }
d67281a7 1832
fc03df7a
UD
1833 /* Determine how much room for descriptors we should initially
1834 allocate. This might need to change later if we cap the number
1835 with MAXCONN. */
1836 const long int nfds = sysconf (_SC_OPEN_MAX);
1837#define MINCONN 32
1838#define MAXCONN 16384
1839 if (nfds == -1 || nfds > MAXCONN)
1840 nconns = MAXCONN;
1841 else if (nfds < MINCONN)
1842 nconns = MINCONN;
1843 else
1844 nconns = nfds;
1845
1846 /* We need memory to pass descriptors on to the worker threads. */
1847 fdlist = (struct fdlist *) xcalloc (nconns, sizeof (fdlist[0]));
1848 /* Array to keep track when connection was accepted. */
1849 starttime = (time_t *) xcalloc (nconns, sizeof (starttime[0]));
1850
1945c96f
UD
1851 /* In the main thread we execute the loop which handles incoming
1852 connections. */
fc03df7a
UD
1853#ifdef HAVE_EPOLL
1854 int efd = epoll_create (100);
1855 if (efd != -1)
1856 {
1857 main_loop_epoll (efd);
1858 close (efd);
1859 }
1860#endif
1861
1862 main_loop_poll ();
d67281a7 1863}
057685e4
UD
1864
1865
1866/* Look up the uid, gid, and supplementary groups to run nscd as. When
1867 this function is called, we are not listening on the nscd socket yet so
1868 we can just use the ordinary lookup functions without causing a lockup */
1869static void
1870begin_drop_privileges (void)
1871{
a95a08b4 1872 struct passwd *pwd = getpwnam (server_user);
057685e4
UD
1873
1874 if (pwd == NULL)
1875 {
1876 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1877 error (EXIT_FAILURE, 0, _("Failed to run nscd as user '%s'"),
1878 server_user);
1879 }
1880
1881 server_uid = pwd->pw_uid;
1882 server_gid = pwd->pw_gid;
1883
4401d759
UD
1884 /* Save the old UID/GID if we have to change back. */
1885 if (paranoia)
1886 {
1887 old_uid = getuid ();
1888 old_gid = getgid ();
1889 }
1890
a95a08b4
UD
1891 if (getgrouplist (server_user, server_gid, NULL, &server_ngroups) == 0)
1892 {
1893 /* This really must never happen. */
1894 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1895 error (EXIT_FAILURE, errno, _("initial getgrouplist failed"));
1896 }
057685e4 1897
a95a08b4 1898 server_groups = (gid_t *) xmalloc (server_ngroups * sizeof (gid_t));
057685e4
UD
1899
1900 if (getgrouplist (server_user, server_gid, server_groups, &server_ngroups)
1901 == -1)
1902 {
1903 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1904 error (EXIT_FAILURE, errno, _("getgrouplist failed"));
1905 }
1906}
1907
1908
1909/* Call setgroups(), setgid(), and setuid() to drop root privileges and
1910 run nscd as the user specified in the configuration file. */
1911static void
1912finish_drop_privileges (void)
1913{
1f063dca
UD
1914#if defined HAVE_LIBAUDIT && defined HAVE_LIBCAP
1915 /* We need to preserve the capabilities to connect to the audit daemon. */
1916 cap_t new_caps = preserve_capabilities ();
1917#endif
1918
057685e4
UD
1919 if (setgroups (server_ngroups, server_groups) == -1)
1920 {
1921 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1922 error (EXIT_FAILURE, errno, _("setgroups failed"));
1923 }
1924
91287339
UD
1925 int res;
1926 if (paranoia)
1927 res = setresgid (server_gid, server_gid, old_gid);
1928 else
1929 res = setgid (server_gid);
1930 if (res == -1)
057685e4
UD
1931 {
1932 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1933 perror ("setgid");
64d64de6 1934 exit (4);
057685e4
UD
1935 }
1936
91287339
UD
1937 if (paranoia)
1938 res = setresuid (server_uid, server_uid, old_uid);
1939 else
1940 res = setuid (server_uid);
1941 if (res == -1)
057685e4
UD
1942 {
1943 dbg_log (_("Failed to run nscd as user '%s'"), server_user);
1944 perror ("setuid");
64d64de6 1945 exit (4);
057685e4 1946 }
1f063dca
UD
1947
1948#if defined HAVE_LIBAUDIT && defined HAVE_LIBCAP
1949 /* Remove the temporary capabilities. */
1950 install_real_capabilities (new_caps);
1951#endif
057685e4 1952}