1 /* Inner loops of cache daemon.
2 Copyright (C) 1998-2017 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, see <http://www.gnu.org/licenses/>. */
35 #include <arpa/inet.h>
37 # include <linux/netlink.h>
38 # include <linux/rtnetlink.h>
41 # include <sys/epoll.h>
44 # include <sys/inotify.h>
47 #include <sys/param.h>
50 # include <sys/sendfile.h>
52 #include <sys/socket.h>
59 #include <resolv/resolv.h>
61 #include <kernel-features.h>
62 #include <libc-internal.h>
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
;
71 static gid_t
*server_groups
;
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",
100 [INITGROUPS
] = "INITGROUPS",
101 [GETSERVBYNAME
] = "GETSERVBYNAME",
102 [GETSERVBYPORT
] = "GETSERVBYPORT",
103 [GETFDSERV
] = "GETFDSERV",
104 [GETNETGRENT
] = "GETNETGRENT",
105 [INNETGR
] = "INNETGR",
106 [GETFDNETGR
] = "GETFDNETGR"
109 /* The control data structures for the services. */
110 struct database_dyn dbs
[lastdb
] =
113 .lock
= PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
,
114 .prune_lock
= PTHREAD_MUTEX_INITIALIZER
,
115 .prune_run_lock
= PTHREAD_MUTEX_INITIALIZER
,
121 .max_db_size
= DEFAULT_MAX_DB_SIZE
,
122 .suggested_module
= DEFAULT_SUGGESTED_MODULE
,
123 .db_filename
= _PATH_NSCD_PASSWD_DB
,
124 .disabled_iov
= &pwd_iov_disabled
,
132 .lock
= PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
,
133 .prune_lock
= PTHREAD_MUTEX_INITIALIZER
,
134 .prune_run_lock
= PTHREAD_MUTEX_INITIALIZER
,
140 .max_db_size
= DEFAULT_MAX_DB_SIZE
,
141 .suggested_module
= DEFAULT_SUGGESTED_MODULE
,
142 .db_filename
= _PATH_NSCD_GROUP_DB
,
143 .disabled_iov
= &grp_iov_disabled
,
151 .lock
= PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
,
152 .prune_lock
= PTHREAD_MUTEX_INITIALIZER
,
153 .prune_run_lock
= PTHREAD_MUTEX_INITIALIZER
,
157 .propagate
= 0, /* Not used. */
159 .max_db_size
= DEFAULT_MAX_DB_SIZE
,
160 .suggested_module
= DEFAULT_SUGGESTED_MODULE
,
161 .db_filename
= _PATH_NSCD_HOSTS_DB
,
162 .disabled_iov
= &hst_iov_disabled
,
170 .lock
= PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
,
171 .prune_lock
= PTHREAD_MUTEX_INITIALIZER
,
172 .prune_run_lock
= PTHREAD_MUTEX_INITIALIZER
,
176 .propagate
= 0, /* Not used. */
178 .max_db_size
= DEFAULT_MAX_DB_SIZE
,
179 .suggested_module
= DEFAULT_SUGGESTED_MODULE
,
180 .db_filename
= _PATH_NSCD_SERVICES_DB
,
181 .disabled_iov
= &serv_iov_disabled
,
189 .lock
= PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
,
190 .prune_lock
= PTHREAD_MUTEX_INITIALIZER
,
191 .prune_run_lock
= PTHREAD_MUTEX_INITIALIZER
,
195 .propagate
= 0, /* Not used. */
197 .max_db_size
= DEFAULT_MAX_DB_SIZE
,
198 .suggested_module
= DEFAULT_SUGGESTED_MODULE
,
199 .db_filename
= _PATH_NSCD_NETGROUP_DB
,
200 .disabled_iov
= &netgroup_iov_disabled
,
210 /* Mapping of request type to database. */
214 struct database_dyn
*db
;
215 } const reqinfo
[LASTREQ
] =
217 [GETPWBYNAME
] = { true, &dbs
[pwddb
] },
218 [GETPWBYUID
] = { true, &dbs
[pwddb
] },
219 [GETGRBYNAME
] = { true, &dbs
[grpdb
] },
220 [GETGRBYGID
] = { true, &dbs
[grpdb
] },
221 [GETHOSTBYNAME
] = { true, &dbs
[hstdb
] },
222 [GETHOSTBYNAMEv6
] = { true, &dbs
[hstdb
] },
223 [GETHOSTBYADDR
] = { true, &dbs
[hstdb
] },
224 [GETHOSTBYADDRv6
] = { true, &dbs
[hstdb
] },
225 [SHUTDOWN
] = { false, NULL
},
226 [GETSTAT
] = { false, NULL
},
227 [SHUTDOWN
] = { false, NULL
},
228 [GETFDPW
] = { false, &dbs
[pwddb
] },
229 [GETFDGR
] = { false, &dbs
[grpdb
] },
230 [GETFDHST
] = { false, &dbs
[hstdb
] },
231 [GETAI
] = { true, &dbs
[hstdb
] },
232 [INITGROUPS
] = { true, &dbs
[grpdb
] },
233 [GETSERVBYNAME
] = { true, &dbs
[servdb
] },
234 [GETSERVBYPORT
] = { true, &dbs
[servdb
] },
235 [GETFDSERV
] = { false, &dbs
[servdb
] },
236 [GETNETGRENT
] = { true, &dbs
[netgrdb
] },
237 [INNETGR
] = { true, &dbs
[netgrdb
] },
238 [GETFDNETGR
] = { false, &dbs
[netgrdb
] }
242 /* Initial number of threads to use. */
244 /* Maximum number of threads to use. */
245 int max_nthreads
= 32;
247 /* Socket for incoming connections. */
251 /* Inotify descriptor. */
256 /* Descriptor for netlink status updates. */
257 static int nl_status_fd
= -1;
260 #ifndef __ASSUME_ACCEPT4
261 static int have_accept4
;
264 /* Number of times clients had to wait. */
265 unsigned long int client_queued
;
269 writeall (int fd
, const void *buf
, size_t len
)
275 ret
= TEMP_FAILURE_RETRY (send (fd
, buf
, n
, MSG_NOSIGNAL
));
278 buf
= (const char *) buf
+ ret
;
282 return ret
< 0 ? ret
: len
- n
;
288 sendfileall (int tofd
, int fromfd
, off_t off
, size_t len
)
295 ret
= TEMP_FAILURE_RETRY (sendfile (tofd
, fromfd
, &off
, n
));
301 return ret
< 0 ? ret
: len
- n
;
309 /* The following three are not really used, they are symbolic constants. */
315 use_he_begin
= use_he
| use_begin
,
316 use_he_end
= use_he
| use_end
,
318 use_data_begin
= use_data
| use_begin
,
319 use_data_end
= use_data
| use_end
,
320 use_data_first
= use_data_begin
| use_first
325 check_use (const char *data
, nscd_ssize_t first_free
, uint8_t *usemap
,
326 enum usekey use
, ref_t start
, size_t len
)
330 if (start
> first_free
|| start
+ len
> first_free
331 || (start
& BLOCK_ALIGN_M1
))
334 if (usemap
[start
] == use_not
)
336 /* Add the start marker. */
337 usemap
[start
] = use
| use_begin
;
341 if (usemap
[++start
] != use_not
)
346 /* Add the end marker. */
347 usemap
[start
] = use
| use_end
;
349 else if ((usemap
[start
] & ~use_first
) == ((use
| use_begin
) & ~use_first
))
351 /* Hash entries can't be shared. */
355 usemap
[start
] |= (use
& use_first
);
359 if (usemap
[++start
] != use
)
362 if (usemap
[++start
] != (use
| use_end
))
366 /* Points to a wrong object or somewhere in the middle. */
373 /* Verify data in persistent database. */
375 verify_persistent_db (void *mem
, struct database_pers_head
*readhead
, int dbnr
)
377 assert (dbnr
== pwddb
|| dbnr
== grpdb
|| dbnr
== hstdb
|| dbnr
== servdb
380 time_t now
= time (NULL
);
382 struct database_pers_head
*head
= mem
;
383 struct database_pers_head head_copy
= *head
;
385 /* Check that the header that was read matches the head in the database. */
386 if (memcmp (head
, readhead
, sizeof (*head
)) != 0)
389 /* First some easy tests: make sure the database header is sane. */
390 if (head
->version
!= DB_VERSION
391 || head
->header_size
!= sizeof (*head
)
392 /* We allow a timestamp to be one hour ahead of the current time.
393 This should cover daylight saving time changes. */
394 || head
->timestamp
> now
+ 60 * 60 + 60
395 || (head
->gc_cycle
& 1)
397 || (size_t) head
->module
> INT32_MAX
/ sizeof (ref_t
)
398 || (size_t) head
->data_size
> INT32_MAX
- head
->module
* sizeof (ref_t
)
399 || head
->first_free
< 0
400 || head
->first_free
> head
->data_size
401 || (head
->first_free
& BLOCK_ALIGN_M1
) != 0
402 || head
->maxnentries
< 0
403 || head
->maxnsearched
< 0)
406 uint8_t *usemap
= calloc (head
->first_free
, 1);
410 const char *data
= (char *) &head
->array
[roundup (head
->module
,
411 ALIGN
/ sizeof (ref_t
))];
413 nscd_ssize_t he_cnt
= 0;
414 for (nscd_ssize_t cnt
= 0; cnt
< head
->module
; ++cnt
)
416 ref_t trail
= head
->array
[cnt
];
420 while (work
!= ENDREF
)
422 if (! check_use (data
, head
->first_free
, usemap
, use_he
, work
,
423 sizeof (struct hashentry
)))
426 /* Now we know we can dereference the record. */
427 struct hashentry
*here
= (struct hashentry
*) (data
+ work
);
431 /* Make sure the record is for this type of service. */
432 if (here
->type
>= LASTREQ
433 || reqinfo
[here
->type
].db
!= &dbs
[dbnr
])
436 /* Validate boolean field value. */
437 if (here
->first
!= false && here
->first
!= true)
445 || here
->packet
> head
->first_free
446 || here
->packet
+ sizeof (struct datahead
) > head
->first_free
)
449 struct datahead
*dh
= (struct datahead
*) (data
+ here
->packet
);
451 if (! check_use (data
, head
->first_free
, usemap
,
452 use_data
| (here
->first
? use_first
: 0),
453 here
->packet
, dh
->allocsize
))
456 if (dh
->allocsize
< sizeof (struct datahead
)
457 || dh
->recsize
> dh
->allocsize
458 || (dh
->notfound
!= false && dh
->notfound
!= true)
459 || (dh
->usable
!= false && dh
->usable
!= true))
462 if (here
->key
< here
->packet
+ sizeof (struct datahead
)
463 || here
->key
> here
->packet
+ dh
->allocsize
464 || here
->key
+ here
->len
> here
->packet
+ dh
->allocsize
)
470 /* A circular list, this must not happen. */
473 trail
= ((struct hashentry
*) (data
+ trail
))->next
;
478 if (he_cnt
!= head
->nentries
)
481 /* See if all data and keys had at least one reference from
482 he->first == true hashentry. */
483 for (ref_t idx
= 0; idx
< head
->first_free
; ++idx
)
485 if (usemap
[idx
] == use_data_begin
)
489 /* Finally, make sure the database hasn't changed since the first test. */
490 if (memcmp (mem
, &head_copy
, sizeof (*head
)) != 0)
503 # define EXTRA_O_FLAGS O_CLOEXEC
505 # define EXTRA_O_FLAGS 0
509 /* Initialize database information structures. */
513 /* Look up unprivileged uid/gid/groups before we start listening on the
515 if (server_user
!= NULL
)
516 begin_drop_privileges ();
519 /* No configuration for this value, assume a default. */
522 for (size_t cnt
= 0; cnt
< lastdb
; ++cnt
)
523 if (dbs
[cnt
].enabled
)
525 pthread_rwlock_init (&dbs
[cnt
].lock
, NULL
);
526 pthread_mutex_init (&dbs
[cnt
].memlock
, NULL
);
528 if (dbs
[cnt
].persistent
)
530 /* Try to open the appropriate file on disk. */
531 int fd
= open (dbs
[cnt
].db_filename
, O_RDWR
| EXTRA_O_FLAGS
);
538 struct database_pers_head head
;
539 ssize_t n
= TEMP_FAILURE_RETRY (read (fd
, &head
,
541 if (n
!= sizeof (head
) || fstat64 (fd
, &st
) != 0)
544 /* The code is single-threaded at this point so
545 using strerror is just fine. */
546 msg
= strerror (errno
);
548 dbg_log (_("invalid persistent database file \"%s\": %s"),
549 dbs
[cnt
].db_filename
, msg
);
550 unlink (dbs
[cnt
].db_filename
);
552 else if (head
.module
== 0 && head
.data_size
== 0)
554 /* The file has been created, but the head has not
555 been initialized yet. */
556 msg
= _("uninitialized header");
559 else if (head
.header_size
!= (int) sizeof (head
))
561 msg
= _("header size does not match");
564 else if ((total
= (sizeof (head
)
565 + roundup (head
.module
* sizeof (ref_t
),
569 || total
< sizeof (head
))
571 msg
= _("file size does not match");
574 /* Note we map with the maximum size allowed for the
575 database. This is likely much larger than the
576 actual file size. This is OK on most OSes since
577 extensions of the underlying file will
578 automatically translate more pages available for
580 else if ((mem
= mmap (NULL
, dbs
[cnt
].max_db_size
,
581 PROT_READ
| PROT_WRITE
,
585 else if (!verify_persistent_db (mem
, &head
, cnt
))
588 msg
= _("verification failed");
593 /* Success. We have the database. */
595 dbs
[cnt
].memsize
= total
;
596 dbs
[cnt
].data
= (char *)
597 &dbs
[cnt
].head
->array
[roundup (dbs
[cnt
].head
->module
,
598 ALIGN
/ sizeof (ref_t
))];
599 dbs
[cnt
].mmap_used
= true;
601 if (dbs
[cnt
].suggested_module
> head
.module
)
602 dbg_log (_("suggested size of table for database %s larger than the persistent database's table"),
607 /* We also need a read-only descriptor. */
610 dbs
[cnt
].ro_fd
= open (dbs
[cnt
].db_filename
,
611 O_RDONLY
| EXTRA_O_FLAGS
);
612 if (dbs
[cnt
].ro_fd
== -1)
614 cannot create read-only descriptor for \"%s\"; no mmap"),
615 dbs
[cnt
].db_filename
);
618 // XXX Shall we test whether the descriptors actually
619 // XXX point to the same file?
622 /* Close the file descriptors in case something went
623 wrong in which case the variable have not been
628 else if (errno
== EACCES
)
629 do_exit (EXIT_FAILURE
, 0, _("cannot access '%s'"),
630 dbs
[cnt
].db_filename
);
633 if (dbs
[cnt
].head
== NULL
)
635 /* No database loaded. Allocate the data structure,
637 struct database_pers_head head
;
638 size_t total
= (sizeof (head
)
639 + roundup (dbs
[cnt
].suggested_module
640 * sizeof (ref_t
), ALIGN
)
641 + (dbs
[cnt
].suggested_module
642 * DEFAULT_DATASIZE_PER_BUCKET
));
644 /* Try to create the database. If we do not need a
645 persistent database create a temporary file. */
648 if (dbs
[cnt
].persistent
)
650 fd
= open (dbs
[cnt
].db_filename
,
651 O_RDWR
| O_CREAT
| O_EXCL
| O_TRUNC
| EXTRA_O_FLAGS
,
653 if (fd
!= -1 && dbs
[cnt
].shared
)
654 ro_fd
= open (dbs
[cnt
].db_filename
,
655 O_RDONLY
| EXTRA_O_FLAGS
);
659 char fname
[] = _PATH_NSCD_XYZ_DB_TMP
;
660 fd
= mkostemp (fname
, EXTRA_O_FLAGS
);
662 /* We do not need the file name anymore after we
663 opened another file descriptor in read-only mode. */
667 ro_fd
= open (fname
, O_RDONLY
| EXTRA_O_FLAGS
);
677 dbg_log (_("database for %s corrupted or simultaneously used; remove %s manually if necessary and restart"),
678 dbnames
[cnt
], dbs
[cnt
].db_filename
);
679 do_exit (1, 0, NULL
);
682 if (dbs
[cnt
].persistent
)
683 dbg_log (_("cannot create %s; no persistent database used"),
684 dbs
[cnt
].db_filename
);
686 dbg_log (_("cannot create %s; no sharing possible"),
687 dbs
[cnt
].db_filename
);
689 dbs
[cnt
].persistent
= 0;
690 // XXX remember: no mmap
694 /* Tell the user if we could not create the read-only
696 if (ro_fd
== -1 && dbs
[cnt
].shared
)
698 cannot create read-only descriptor for \"%s\"; no mmap"),
699 dbs
[cnt
].db_filename
);
701 /* Before we create the header, initialize the hash
702 table. That way if we get interrupted while writing
703 the header we can recognize a partially initialized
705 size_t ps
= sysconf (_SC_PAGESIZE
);
707 assert (~ENDREF
== 0);
708 memset (tmpbuf
, '\xff', ps
);
710 size_t remaining
= dbs
[cnt
].suggested_module
* sizeof (ref_t
);
711 off_t offset
= sizeof (head
);
714 if (offset
% ps
!= 0)
716 towrite
= MIN (remaining
, ps
- (offset
% ps
));
717 if (pwrite (fd
, tmpbuf
, towrite
, offset
) != towrite
)
720 remaining
-= towrite
;
723 while (remaining
> ps
)
725 if (pwrite (fd
, tmpbuf
, ps
, offset
) == -1)
732 && pwrite (fd
, tmpbuf
, remaining
, offset
) != remaining
)
735 /* Create the header of the file. */
736 struct database_pers_head head
=
738 .version
= DB_VERSION
,
739 .header_size
= sizeof (head
),
740 .module
= dbs
[cnt
].suggested_module
,
741 .data_size
= (dbs
[cnt
].suggested_module
742 * DEFAULT_DATASIZE_PER_BUCKET
),
747 if ((TEMP_FAILURE_RETRY (write (fd
, &head
, sizeof (head
)))
749 || (TEMP_FAILURE_RETRY_VAL (posix_fallocate (fd
, 0, total
))
751 || (mem
= mmap (NULL
, dbs
[cnt
].max_db_size
,
752 PROT_READ
| PROT_WRITE
,
753 MAP_SHARED
, fd
, 0)) == MAP_FAILED
)
756 unlink (dbs
[cnt
].db_filename
);
757 dbg_log (_("cannot write to database file %s: %s"),
758 dbs
[cnt
].db_filename
, strerror (errno
));
759 dbs
[cnt
].persistent
= 0;
765 dbs
[cnt
].data
= (char *)
766 &dbs
[cnt
].head
->array
[roundup (dbs
[cnt
].head
->module
,
767 ALIGN
/ sizeof (ref_t
))];
768 dbs
[cnt
].memsize
= total
;
769 dbs
[cnt
].mmap_used
= true;
771 /* Remember the descriptors. */
773 dbs
[cnt
].ro_fd
= ro_fd
;
785 #if !defined O_CLOEXEC || !defined __ASSUME_O_CLOEXEC
786 /* We do not check here whether the O_CLOEXEC provided to the
787 open call was successful or not. The two fcntl calls are
788 only performed once each per process start-up and therefore
789 is not noticeable at all. */
791 && ((dbs
[cnt
].wr_fd
!= -1
792 && fcntl (dbs
[cnt
].wr_fd
, F_SETFD
, FD_CLOEXEC
) == -1)
793 || (dbs
[cnt
].ro_fd
!= -1
794 && fcntl (dbs
[cnt
].ro_fd
, F_SETFD
, FD_CLOEXEC
) == -1)))
797 cannot set socket to close on exec: %s; disabling paranoia mode"),
803 if (dbs
[cnt
].head
== NULL
)
805 /* We do not use the persistent database. Just
806 create an in-memory data structure. */
807 assert (! dbs
[cnt
].persistent
);
809 dbs
[cnt
].head
= xmalloc (sizeof (struct database_pers_head
)
810 + (dbs
[cnt
].suggested_module
812 memset (dbs
[cnt
].head
, '\0', sizeof (struct database_pers_head
));
813 assert (~ENDREF
== 0);
814 memset (dbs
[cnt
].head
->array
, '\xff',
815 dbs
[cnt
].suggested_module
* sizeof (ref_t
));
816 dbs
[cnt
].head
->module
= dbs
[cnt
].suggested_module
;
817 dbs
[cnt
].head
->data_size
= (DEFAULT_DATASIZE_PER_BUCKET
818 * dbs
[cnt
].head
->module
);
819 dbs
[cnt
].data
= xmalloc (dbs
[cnt
].head
->data_size
);
820 dbs
[cnt
].head
->first_free
= 0;
823 assert (dbs
[cnt
].ro_fd
== -1);
827 /* Create the socket. */
828 sock
= socket (AF_UNIX
, SOCK_STREAM
| SOCK_CLOEXEC
| SOCK_NONBLOCK
, 0);
831 dbg_log (_("cannot open socket: %s"), strerror (errno
));
832 do_exit (errno
== EACCES
? 4 : 1, 0, NULL
);
834 /* Bind a name to the socket. */
835 struct sockaddr_un sock_addr
;
836 sock_addr
.sun_family
= AF_UNIX
;
837 strcpy (sock_addr
.sun_path
, _PATH_NSCDSOCKET
);
838 if (bind (sock
, (struct sockaddr
*) &sock_addr
, sizeof (sock_addr
)) < 0)
840 dbg_log ("%s: %s", _PATH_NSCDSOCKET
, strerror (errno
));
841 do_exit (errno
== EACCES
? 4 : 1, 0, NULL
);
844 /* Set permissions for the socket. */
845 chmod (_PATH_NSCDSOCKET
, DEFFILEMODE
);
847 /* Set the socket up to accept connections. */
848 if (listen (sock
, SOMAXCONN
) < 0)
850 dbg_log (_("cannot enable socket to accept connections: %s"),
852 do_exit (1, 0, NULL
);
856 if (dbs
[hstdb
].enabled
)
858 /* Try to open netlink socket to monitor network setting changes. */
859 nl_status_fd
= socket (AF_NETLINK
,
860 SOCK_RAW
| SOCK_CLOEXEC
| SOCK_NONBLOCK
,
862 if (nl_status_fd
!= -1)
864 struct sockaddr_nl snl
;
865 memset (&snl
, '\0', sizeof (snl
));
866 snl
.nl_family
= AF_NETLINK
;
867 /* XXX Is this the best set to use? */
868 snl
.nl_groups
= (RTMGRP_IPV4_IFADDR
| RTMGRP_TC
| RTMGRP_IPV4_MROUTE
869 | RTMGRP_IPV4_ROUTE
| RTMGRP_IPV4_RULE
870 | RTMGRP_IPV6_IFADDR
| RTMGRP_IPV6_MROUTE
871 | RTMGRP_IPV6_ROUTE
| RTMGRP_IPV6_IFINFO
872 | RTMGRP_IPV6_PREFIX
);
874 if (bind (nl_status_fd
, (struct sockaddr
*) &snl
, sizeof (snl
)) != 0)
876 close (nl_status_fd
);
881 /* Start the timestamp process. */
882 dbs
[hstdb
].head
->extra_data
[NSCD_HST_IDX_CONF_TIMESTAMP
]
883 = __bump_nl_timestamp ();
889 /* Change to unprivileged uid/gid/groups if specified in config file */
890 if (server_user
!= NULL
)
891 finish_drop_privileges ();
895 #define TRACED_FILE_MASK (IN_DELETE_SELF | IN_CLOSE_WRITE | IN_MOVE_SELF)
896 #define TRACED_DIR_MASK (IN_DELETE_SELF | IN_CREATE | IN_MOVED_TO | IN_MOVE_SELF)
898 install_watches (struct traced_file
*finfo
)
900 /* Use inotify support if we have it. */
901 if (finfo
->inotify_descr
[TRACED_FILE
] < 0)
902 finfo
->inotify_descr
[TRACED_FILE
] = inotify_add_watch (inotify_fd
,
905 if (finfo
->inotify_descr
[TRACED_FILE
] < 0)
907 dbg_log (_("disabled inotify-based monitoring for file `%s': %s"),
908 finfo
->fname
, strerror (errno
));
911 dbg_log (_("monitoring file `%s` (%d)"),
912 finfo
->fname
, finfo
->inotify_descr
[TRACED_FILE
]);
913 /* Additionally listen for events in the file's parent directory.
914 We do this because the file to be watched might be
915 deleted and then added back again. When it is added back again
916 we must re-add the watch. We must also cover IN_MOVED_TO to
917 detect a file being moved into the directory. */
918 if (finfo
->inotify_descr
[TRACED_DIR
] < 0)
919 finfo
->inotify_descr
[TRACED_DIR
] = inotify_add_watch (inotify_fd
,
922 if (finfo
->inotify_descr
[TRACED_DIR
] < 0)
924 dbg_log (_("disabled inotify-based monitoring for directory `%s': %s"),
925 finfo
->fname
, strerror (errno
));
928 dbg_log (_("monitoring directory `%s` (%d)"),
929 finfo
->dname
, finfo
->inotify_descr
[TRACED_DIR
]);
933 /* Register the file in FINFO as a traced file for the database DBS[DBIX].
935 We support registering multiple files per database. Each call to
936 register_traced_file adds to the list of registered files.
938 When we prune the database, either through timeout or a request to
939 invalidate, we will check to see if any of the registered files has changed.
940 When we accept new connections to handle a cache request we will also
941 check to see if any of the registered files has changed.
943 If we have inotify support then we install an inotify fd to notify us of
944 file deletion or modification, both of which will require we invalidate
945 the cache for the database. Without inotify support we stat the file and
946 store st_mtime to determine if the file has been modified. */
948 register_traced_file (size_t dbidx
, struct traced_file
*finfo
)
950 /* If the database is disabled or file checking is disabled
951 then ignore the registration. */
952 if (! dbs
[dbidx
].enabled
|| ! dbs
[dbidx
].check_file
)
955 if (__glibc_unlikely (debug_level
> 0))
956 dbg_log (_("monitoring file %s for database %s"),
957 finfo
->fname
, dbnames
[dbidx
]);
960 install_watches (finfo
);
963 if (stat64 (finfo
->fname
, &st
) < 0)
965 /* We cannot stat() the file. Set mtime to zero and try again later. */
966 dbg_log (_("stat failed for file `%s'; will try again later: %s"),
967 finfo
->fname
, strerror (errno
));
971 finfo
->mtime
= st
.st_mtime
;
973 /* Queue up the file name. */
974 finfo
->next
= dbs
[dbidx
].traced_files
;
975 dbs
[dbidx
].traced_files
= finfo
;
979 /* Close the connections. */
988 invalidate_cache (char *key
, int fd
)
993 for (number
= pwddb
; number
< lastdb
; ++number
)
994 if (strcmp (key
, dbnames
[number
]) == 0)
996 struct traced_file
*runp
= dbs
[number
].traced_files
;
999 /* Make sure we reload from file when checking mtime. */
1002 /* During an invalidation we try to reload the traced
1003 file watches. This allows the user to re-sync if
1004 inotify events were lost. Similar to what we do during
1006 install_watches (runp
);
1008 if (runp
->call_res_init
)
1018 if (number
== lastdb
)
1021 writeall (fd
, &resp
, sizeof (resp
));
1025 if (dbs
[number
].enabled
)
1027 pthread_mutex_lock (&dbs
[number
].prune_run_lock
);
1028 prune_cache (&dbs
[number
], LONG_MAX
, fd
);
1029 pthread_mutex_unlock (&dbs
[number
].prune_run_lock
);
1034 writeall (fd
, &resp
, sizeof (resp
));
1041 send_ro_fd (struct database_dyn
*db
, char *key
, int fd
)
1043 /* If we do not have an read-only file descriptor do nothing. */
1044 if (db
->ro_fd
== -1)
1047 /* We need to send some data along with the descriptor. */
1048 uint64_t mapsize
= (db
->head
->data_size
1049 + roundup (db
->head
->module
* sizeof (ref_t
), ALIGN
)
1050 + sizeof (struct database_pers_head
));
1051 struct iovec iov
[2];
1052 iov
[0].iov_base
= key
;
1053 iov
[0].iov_len
= strlen (key
) + 1;
1054 iov
[1].iov_base
= &mapsize
;
1055 iov
[1].iov_len
= sizeof (mapsize
);
1057 /* Prepare the control message to transfer the descriptor. */
1061 char bytes
[CMSG_SPACE (sizeof (int))];
1063 struct msghdr msg
= { .msg_iov
= iov
, .msg_iovlen
= 2,
1064 .msg_control
= buf
.bytes
,
1065 .msg_controllen
= sizeof (buf
) };
1066 struct cmsghdr
*cmsg
= CMSG_FIRSTHDR (&msg
);
1068 cmsg
->cmsg_level
= SOL_SOCKET
;
1069 cmsg
->cmsg_type
= SCM_RIGHTS
;
1070 cmsg
->cmsg_len
= CMSG_LEN (sizeof (int));
1072 int *ip
= (int *) CMSG_DATA (cmsg
);
1075 msg
.msg_controllen
= cmsg
->cmsg_len
;
1077 /* Send the control message. We repeat when we are interrupted but
1078 everything else is ignored. */
1079 #ifndef MSG_NOSIGNAL
1080 # define MSG_NOSIGNAL 0
1082 (void) TEMP_FAILURE_RETRY (sendmsg (fd
, &msg
, MSG_NOSIGNAL
));
1084 if (__glibc_unlikely (debug_level
> 0))
1085 dbg_log (_("provide access to FD %d, for %s"), db
->ro_fd
, key
);
1087 #endif /* SCM_RIGHTS */
1090 /* Handle new request. */
1092 handle_request (int fd
, request_header
*req
, void *key
, uid_t uid
, pid_t pid
)
1094 if (__builtin_expect (req
->version
, NSCD_VERSION
) != NSCD_VERSION
)
1096 if (debug_level
> 0)
1098 cannot handle old request version %d; current version is %d"),
1099 req
->version
, NSCD_VERSION
);
1103 /* Perform the SELinux check before we go on to the standard checks. */
1104 if (selinux_enabled
&& nscd_request_avc_has_perm (fd
, req
->type
) != 0)
1106 if (debug_level
> 0)
1115 snprintf (buf
, sizeof (buf
), "/proc/%ld/exe", (long int) pid
);
1116 ssize_t n
= readlink (buf
, buf
, sizeof (buf
) - 1);
1120 request from %ld not handled due to missing permission"), (long int) pid
);
1125 request from '%s' [%ld] not handled due to missing permission"),
1126 buf
, (long int) pid
);
1129 dbg_log (_("request not handled due to missing permission"));
1135 struct database_dyn
*db
= reqinfo
[req
->type
].db
;
1137 /* See whether we can service the request from the cache. */
1138 if (__builtin_expect (reqinfo
[req
->type
].data_request
, true))
1140 if (__builtin_expect (debug_level
, 0) > 0)
1142 if (req
->type
== GETHOSTBYADDR
|| req
->type
== GETHOSTBYADDRv6
)
1144 char buf
[INET6_ADDRSTRLEN
];
1146 dbg_log ("\t%s (%s)", serv2str
[req
->type
],
1147 inet_ntop (req
->type
== GETHOSTBYADDR
1148 ? AF_INET
: AF_INET6
,
1149 key
, buf
, sizeof (buf
)));
1152 dbg_log ("\t%s (%s)", serv2str
[req
->type
], (char *) key
);
1155 /* Is this service enabled? */
1156 if (__glibc_unlikely (!db
->enabled
))
1158 /* No, sent the prepared record. */
1159 if (TEMP_FAILURE_RETRY (send (fd
, db
->disabled_iov
->iov_base
,
1160 db
->disabled_iov
->iov_len
,
1162 != (ssize_t
) db
->disabled_iov
->iov_len
1163 && __builtin_expect (debug_level
, 0) > 0)
1165 /* We have problems sending the result. */
1167 dbg_log (_("cannot write result: %s"),
1168 strerror_r (errno
, buf
, sizeof (buf
)));
1174 /* Be sure we can read the data. */
1175 if (__glibc_unlikely (pthread_rwlock_tryrdlock (&db
->lock
) != 0))
1177 ++db
->head
->rdlockdelayed
;
1178 pthread_rwlock_rdlock (&db
->lock
);
1181 /* See whether we can handle it from the cache. */
1182 struct datahead
*cached
;
1183 cached
= (struct datahead
*) cache_search (req
->type
, key
, req
->key_len
,
1187 /* Hurray it's in the cache. */
1190 #ifdef HAVE_SENDFILE
1191 if (__glibc_likely (db
->mmap_used
))
1193 assert (db
->wr_fd
!= -1);
1194 assert ((char *) cached
->data
> (char *) db
->data
);
1195 assert ((char *) cached
->data
- (char *) db
->head
1197 <= (sizeof (struct database_pers_head
)
1198 + db
->head
->module
* sizeof (ref_t
)
1199 + db
->head
->data_size
));
1200 nwritten
= sendfileall (fd
, db
->wr_fd
,
1201 (char *) cached
->data
1202 - (char *) db
->head
, cached
->recsize
);
1203 # ifndef __ASSUME_SENDFILE
1204 if (nwritten
== -1 && errno
== ENOSYS
)
1209 # ifndef __ASSUME_SENDFILE
1213 nwritten
= writeall (fd
, cached
->data
, cached
->recsize
);
1215 if (nwritten
!= cached
->recsize
1216 && __builtin_expect (debug_level
, 0) > 0)
1218 /* We have problems sending the result. */
1220 dbg_log (_("cannot write result: %s"),
1221 strerror_r (errno
, buf
, sizeof (buf
)));
1224 pthread_rwlock_unlock (&db
->lock
);
1229 pthread_rwlock_unlock (&db
->lock
);
1231 else if (__builtin_expect (debug_level
, 0) > 0)
1233 if (req
->type
== INVALIDATE
)
1234 dbg_log ("\t%s (%s)", serv2str
[req
->type
], (char *) key
);
1236 dbg_log ("\t%s", serv2str
[req
->type
]);
1239 /* Handle the request. */
1243 addpwbyname (db
, fd
, req
, key
, uid
);
1247 addpwbyuid (db
, fd
, req
, key
, uid
);
1251 addgrbyname (db
, fd
, req
, key
, uid
);
1255 addgrbygid (db
, fd
, req
, key
, uid
);
1259 addhstbyname (db
, fd
, req
, key
, uid
);
1262 case GETHOSTBYNAMEv6
:
1263 addhstbynamev6 (db
, fd
, req
, key
, uid
);
1267 addhstbyaddr (db
, fd
, req
, key
, uid
);
1270 case GETHOSTBYADDRv6
:
1271 addhstbyaddrv6 (db
, fd
, req
, key
, uid
);
1275 addhstai (db
, fd
, req
, key
, uid
);
1279 addinitgroups (db
, fd
, req
, key
, uid
);
1283 addservbyname (db
, fd
, req
, key
, uid
);
1287 addservbyport (db
, fd
, req
, key
, uid
);
1291 addgetnetgrent (db
, fd
, req
, key
, uid
);
1295 addinnetgr (db
, fd
, req
, key
, uid
);
1302 /* Get the callers credentials. */
1304 struct ucred caller
;
1305 socklen_t optlen
= sizeof (caller
);
1307 if (getsockopt (fd
, SOL_SOCKET
, SO_PEERCRED
, &caller
, &optlen
) < 0)
1311 dbg_log (_("error getting caller's id: %s"),
1312 strerror_r (errno
, buf
, sizeof (buf
)));
1318 /* Some systems have no SO_PEERCRED implementation. They don't
1319 care about security so we don't as well. */
1324 /* Accept shutdown, getstat and invalidate only from root. For
1325 the stat call also allow the user specified in the config file. */
1326 if (req
->type
== GETSTAT
)
1328 if (uid
== 0 || uid
== stat_uid
)
1329 send_stats (fd
, dbs
);
1333 if (req
->type
== INVALIDATE
)
1334 invalidate_cache (key
, fd
);
1336 termination_handler (0);
1346 send_ro_fd (reqinfo
[req
->type
].db
, key
, fd
);
1351 /* Ignore the command, it's nothing we know. */
1357 /* Restart the process. */
1361 /* First determine the parameters. We do not use the parameters
1362 passed to main() since in case nscd is started by running the
1363 dynamic linker this will not work. Yes, this is not the usual
1364 case but nscd is part of glibc and we occasionally do this. */
1365 size_t buflen
= 1024;
1366 char *buf
= alloca (buflen
);
1368 int fd
= open ("/proc/self/cmdline", O_RDONLY
);
1372 cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
1381 ssize_t n
= TEMP_FAILURE_RETRY (read (fd
, buf
+ readlen
,
1386 cannot read /proc/self/cmdline: %s; disabling paranoia mode"),
1396 if (readlen
< buflen
)
1399 /* We might have to extend the buffer. */
1400 size_t old_buflen
= buflen
;
1401 char *newp
= extend_alloca (buf
, buflen
, 2 * buflen
);
1402 buf
= memmove (newp
, buf
, old_buflen
);
1407 /* Parse the command line. Worst case scenario: every two
1408 characters form one parameter (one character plus NUL). */
1409 char **argv
= alloca ((readlen
/ 2 + 1) * sizeof (argv
[0]));
1413 while (cp
< buf
+ readlen
)
1416 cp
= (char *) rawmemchr (cp
, '\0') + 1;
1420 /* Second, change back to the old user if we changed it. */
1421 if (server_user
!= NULL
)
1423 if (setresuid (old_uid
, old_uid
, old_uid
) != 0)
1426 cannot change to old UID: %s; disabling paranoia mode"),
1433 if (setresgid (old_gid
, old_gid
, old_gid
) != 0)
1436 cannot change to old GID: %s; disabling paranoia mode"),
1439 ignore_value (setuid (server_uid
));
1445 /* Next change back to the old working directory. */
1446 if (chdir (oldcwd
) == -1)
1449 cannot change to old working directory: %s; disabling paranoia mode"),
1452 if (server_user
!= NULL
)
1454 ignore_value (setuid (server_uid
));
1455 ignore_value (setgid (server_gid
));
1461 /* Synchronize memory. */
1462 int32_t certainly
[lastdb
];
1463 for (int cnt
= 0; cnt
< lastdb
; ++cnt
)
1464 if (dbs
[cnt
].enabled
)
1466 /* Make sure nobody keeps using the database. */
1467 dbs
[cnt
].head
->timestamp
= 0;
1468 certainly
[cnt
] = dbs
[cnt
].head
->nscd_certainly_running
;
1469 dbs
[cnt
].head
->nscd_certainly_running
= 0;
1471 if (dbs
[cnt
].persistent
)
1473 msync (dbs
[cnt
].head
, dbs
[cnt
].memsize
, MS_ASYNC
);
1476 /* The preparations are done. */
1478 char pathbuf
[PATH_MAX
];
1482 /* Try to exec the real nscd program so the process name (as reported
1483 in /proc/PID/status) will be 'nscd', but fall back to /proc/self/exe
1484 if readlink or the exec with the result of the readlink call fails. */
1485 ssize_t n
= readlink ("/proc/self/exe", pathbuf
, sizeof (pathbuf
) - 1);
1489 execv (pathbuf
, argv
);
1491 execv ("/proc/self/exe", argv
);
1493 /* If we come here, we will never be able to re-exec. */
1494 dbg_log (_("re-exec failed: %s; disabling paranoia mode"),
1497 if (server_user
!= NULL
)
1499 ignore_value (setuid (server_uid
));
1500 ignore_value (setgid (server_gid
));
1502 if (chdir ("/") != 0)
1503 dbg_log (_("cannot change current working directory to \"/\": %s"),
1507 /* Reenable the databases. */
1508 time_t now
= time (NULL
);
1509 for (int cnt
= 0; cnt
< lastdb
; ++cnt
)
1510 if (dbs
[cnt
].enabled
)
1512 dbs
[cnt
].head
->timestamp
= now
;
1513 dbs
[cnt
].head
->nscd_certainly_running
= certainly
[cnt
];
1518 /* List of file descriptors. */
1522 struct fdlist
*next
;
1524 /* Memory allocated for the list. */
1525 static struct fdlist
*fdlist
;
1526 /* List of currently ready-to-read file descriptors. */
1527 static struct fdlist
*readylist
;
1529 /* Conditional variable and mutex to signal availability of entries in
1530 READYLIST. The condvar is initialized dynamically since we might
1531 use a different clock depending on availability. */
1532 static pthread_cond_t readylist_cond
= PTHREAD_COND_INITIALIZER
;
1533 static pthread_mutex_t readylist_lock
= PTHREAD_MUTEX_INITIALIZER
;
1535 /* The clock to use with the condvar. */
1536 static clockid_t timeout_clock
= CLOCK_REALTIME
;
1538 /* Number of threads ready to handle the READYLIST. */
1539 static unsigned long int nready
;
1542 /* Function for the clean-up threads. */
1544 __attribute__ ((__noreturn__
))
1545 nscd_run_prune (void *p
)
1547 const long int my_number
= (long int) p
;
1548 assert (dbs
[my_number
].enabled
);
1550 int dont_need_update
= setup_thread (&dbs
[my_number
]);
1552 time_t now
= time (NULL
);
1554 /* We are running. */
1555 dbs
[my_number
].head
->timestamp
= now
;
1557 struct timespec prune_ts
;
1558 if (__glibc_unlikely (clock_gettime (timeout_clock
, &prune_ts
) == -1))
1559 /* Should never happen. */
1562 /* Compute the initial timeout time. Prevent all the timers to go
1563 off at the same time by adding a db-based value. */
1564 prune_ts
.tv_sec
+= CACHE_PRUNE_INTERVAL
+ my_number
;
1565 dbs
[my_number
].wakeup_time
= now
+ CACHE_PRUNE_INTERVAL
+ my_number
;
1567 pthread_mutex_t
*prune_lock
= &dbs
[my_number
].prune_lock
;
1568 pthread_mutex_t
*prune_run_lock
= &dbs
[my_number
].prune_run_lock
;
1569 pthread_cond_t
*prune_cond
= &dbs
[my_number
].prune_cond
;
1571 pthread_mutex_lock (prune_lock
);
1574 /* Wait, but not forever. */
1576 if (! dbs
[my_number
].clear_cache
)
1577 e
= pthread_cond_timedwait (prune_cond
, prune_lock
, &prune_ts
);
1578 assert (__builtin_expect (e
== 0 || e
== ETIMEDOUT
, 1));
1582 if (e
== ETIMEDOUT
|| now
>= dbs
[my_number
].wakeup_time
1583 || dbs
[my_number
].clear_cache
)
1585 /* We will determine the new timout values based on the
1586 cache content. Should there be concurrent additions to
1587 the cache which are not accounted for in the cache
1588 pruning we want to know about it. Therefore set the
1589 timeout to the maximum. It will be descreased when adding
1590 new entries to the cache, if necessary. */
1591 dbs
[my_number
].wakeup_time
= MAX_TIMEOUT_VALUE
;
1593 /* Unconditionally reset the flag. */
1594 time_t prune_now
= dbs
[my_number
].clear_cache
? LONG_MAX
: now
;
1595 dbs
[my_number
].clear_cache
= 0;
1597 pthread_mutex_unlock (prune_lock
);
1599 /* We use a separate lock for running the prune function (instead
1600 of keeping prune_lock locked) because this enables concurrent
1601 invocations of cache_add which might modify the timeout value. */
1602 pthread_mutex_lock (prune_run_lock
);
1603 next_wait
= prune_cache (&dbs
[my_number
], prune_now
, -1);
1604 pthread_mutex_unlock (prune_run_lock
);
1606 next_wait
= MAX (next_wait
, CACHE_PRUNE_INTERVAL
);
1607 /* If clients cannot determine for sure whether nscd is running
1608 we need to wake up occasionally to update the timestamp.
1609 Wait 90% of the update period. */
1610 #define UPDATE_MAPPING_TIMEOUT (MAPPING_TIMEOUT * 9 / 10)
1611 if (__glibc_unlikely (! dont_need_update
))
1613 next_wait
= MIN (UPDATE_MAPPING_TIMEOUT
, next_wait
);
1614 dbs
[my_number
].head
->timestamp
= now
;
1617 pthread_mutex_lock (prune_lock
);
1619 /* Make it known when we will wake up again. */
1620 if (now
+ next_wait
< dbs
[my_number
].wakeup_time
)
1621 dbs
[my_number
].wakeup_time
= now
+ next_wait
;
1623 next_wait
= dbs
[my_number
].wakeup_time
- now
;
1626 /* The cache was just pruned. Do not do it again now. Just
1627 use the new timeout value. */
1628 next_wait
= dbs
[my_number
].wakeup_time
- now
;
1630 if (clock_gettime (timeout_clock
, &prune_ts
) == -1)
1631 /* Should never happen. */
1634 /* Compute next timeout time. */
1635 prune_ts
.tv_sec
+= next_wait
;
1640 /* This is the main loop. It is replicated in different threads but
1641 the use of the ready list makes sure only one thread handles an
1642 incoming connection. */
1644 __attribute__ ((__noreturn__
))
1645 nscd_run_worker (void *p
)
1649 /* Initial locking. */
1650 pthread_mutex_lock (&readylist_lock
);
1652 /* One more thread available. */
1657 while (readylist
== NULL
)
1658 pthread_cond_wait (&readylist_cond
, &readylist_lock
);
1660 struct fdlist
*it
= readylist
->next
;
1661 if (readylist
->next
== readylist
)
1662 /* Just one entry on the list. */
1665 readylist
->next
= it
->next
;
1667 /* Extract the information and mark the record ready to be used
1672 /* One more thread available. */
1675 /* We are done with the list. */
1676 pthread_mutex_unlock (&readylist_lock
);
1678 #ifndef __ASSUME_ACCEPT4
1679 if (have_accept4
< 0)
1681 /* We do not want to block on a short read or so. */
1682 int fl
= fcntl (fd
, F_GETFL
);
1683 if (fl
== -1 || fcntl (fd
, F_SETFL
, fl
| O_NONBLOCK
) == -1)
1688 /* Now read the request. */
1690 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd
, &req
, sizeof (req
)))
1691 != sizeof (req
), 0))
1693 /* We failed to read data. Note that this also might mean we
1694 failed because we would have blocked. */
1695 if (debug_level
> 0)
1696 dbg_log (_("short read while reading request: %s"),
1697 strerror_r (errno
, buf
, sizeof (buf
)));
1701 /* Check whether this is a valid request type. */
1702 if (req
.type
< GETPWBYNAME
|| req
.type
>= LASTREQ
)
1705 /* Some systems have no SO_PEERCRED implementation. They don't
1706 care about security so we don't as well. */
1711 if (__glibc_unlikely (debug_level
> 0))
1713 struct ucred caller
;
1714 socklen_t optlen
= sizeof (caller
);
1716 if (getsockopt (fd
, SOL_SOCKET
, SO_PEERCRED
, &caller
, &optlen
) == 0)
1720 const pid_t pid
= 0;
1723 /* It should not be possible to crash the nscd with a silly
1724 request (i.e., a terribly large key). We limit the size to 1kb. */
1725 if (__builtin_expect (req
.key_len
, 1) < 0
1726 || __builtin_expect (req
.key_len
, 1) > MAXKEYLEN
)
1728 if (debug_level
> 0)
1729 dbg_log (_("key length in request too long: %d"), req
.key_len
);
1734 char keybuf
[MAXKEYLEN
+ 1];
1736 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd
, keybuf
,
1740 /* Again, this can also mean we would have blocked. */
1741 if (debug_level
> 0)
1742 dbg_log (_("short read while reading request key: %s"),
1743 strerror_r (errno
, buf
, sizeof (buf
)));
1746 keybuf
[req
.key_len
] = '\0';
1748 if (__builtin_expect (debug_level
, 0) > 0)
1753 handle_request: request received (Version = %d) from PID %ld"),
1754 req
.version
, (long int) pid
);
1758 handle_request: request received (Version = %d)"), req
.version
);
1761 /* Phew, we got all the data, now process it. */
1762 handle_request (fd
, &req
, keybuf
, uid
, pid
);
1770 pthread_mutex_lock (&readylist_lock
);
1772 /* One more thread available. */
1779 static unsigned int nconns
;
1784 pthread_mutex_lock (&readylist_lock
);
1786 /* Find an empty entry in FDLIST. */
1788 for (inner
= 0; inner
< nconns
; ++inner
)
1789 if (fdlist
[inner
].next
== NULL
)
1791 assert (inner
< nconns
);
1793 fdlist
[inner
].fd
= fd
;
1795 if (readylist
== NULL
)
1796 readylist
= fdlist
[inner
].next
= &fdlist
[inner
];
1799 fdlist
[inner
].next
= readylist
->next
;
1800 readylist
= readylist
->next
= &fdlist
[inner
];
1803 bool do_signal
= true;
1804 if (__glibc_unlikely (nready
== 0))
1809 /* Try to start another thread to help out. */
1811 if (nthreads
< max_nthreads
1812 && pthread_create (&th
, &attr
, nscd_run_worker
,
1813 (void *) (long int) nthreads
) == 0)
1815 /* We got another thread. */
1817 /* The new thread might need a kick. */
1823 pthread_mutex_unlock (&readylist_lock
);
1825 /* Tell one of the worker threads there is work to do. */
1827 pthread_cond_signal (&readylist_cond
);
1831 /* Check whether restarting should happen. */
1833 restart_p (time_t now
)
1835 return (paranoia
&& readylist
== NULL
&& nready
== nthreads
1836 && now
>= restart_time
);
1840 /* Array for times a connection was accepted. */
1841 static time_t *starttime
;
1844 /* Inotify event for changed file. */
1847 struct inotify_event i
;
1849 # define PATH_MAX 1024
1851 char buf
[sizeof (struct inotify_event
) + PATH_MAX
];
1854 /* Returns 0 if the file is there otherwise -1. */
1856 check_file (struct traced_file
*finfo
)
1859 /* We could check mtime and if different re-add
1860 the watches, and invalidate the database, but we
1861 don't because we are called from inotify_check_files
1862 which should be doing that work. If sufficient inotify
1863 events were lost then the next pruning or invalidation
1864 will do the stat and mtime check. We don't do it here to
1865 keep the logic simple. */
1866 if (stat64 (finfo
->fname
, &st
) < 0)
1871 /* Process the inotify event in INEV. If the event matches any of the files
1872 registered with a database then mark that database as requiring its cache
1873 to be cleared. We indicate the cache needs clearing by setting
1874 TO_CLEAR[DBCNT] to true for the matching database. */
1876 inotify_check_files (bool *to_clear
, union __inev
*inev
)
1878 /* Check which of the files changed. */
1879 for (size_t dbcnt
= 0; dbcnt
< lastdb
; ++dbcnt
)
1881 struct traced_file
*finfo
= dbs
[dbcnt
].traced_files
;
1883 while (finfo
!= NULL
)
1885 /* The configuration file was moved or deleted.
1886 We stop watching it at that point, and reinitialize. */
1887 if (finfo
->inotify_descr
[TRACED_FILE
] == inev
->i
.wd
1888 && ((inev
->i
.mask
& IN_MOVE_SELF
)
1889 || (inev
->i
.mask
& IN_DELETE_SELF
)
1890 || (inev
->i
.mask
& IN_IGNORED
)))
1893 bool moved
= (inev
->i
.mask
& IN_MOVE_SELF
) != 0;
1895 if (check_file (finfo
) == 0)
1897 dbg_log (_("ignored inotify event for `%s` (file exists)"),
1902 dbg_log (_("monitored file `%s` was %s, removing watch"),
1903 finfo
->fname
, moved
? "moved" : "deleted");
1904 /* File was moved out, remove the watch. Watches are
1905 automatically removed when the file is deleted. */
1908 ret
= inotify_rm_watch (inotify_fd
, inev
->i
.wd
);
1910 dbg_log (_("failed to remove file watch `%s`: %s"),
1911 finfo
->fname
, strerror (errno
));
1913 finfo
->inotify_descr
[TRACED_FILE
] = -1;
1914 to_clear
[dbcnt
] = true;
1915 if (finfo
->call_res_init
)
1919 /* The configuration file was open for writing and has just closed.
1920 We reset the cache and reinitialize. */
1921 if (finfo
->inotify_descr
[TRACED_FILE
] == inev
->i
.wd
1922 && inev
->i
.mask
& IN_CLOSE_WRITE
)
1924 /* Mark cache as needing to be cleared and reinitialize. */
1925 dbg_log (_("monitored file `%s` was written to"), finfo
->fname
);
1926 to_clear
[dbcnt
] = true;
1927 if (finfo
->call_res_init
)
1931 /* The parent directory was moved or deleted. We trigger one last
1932 invalidation. At the next pruning or invalidation we may add
1933 this watch back if the file is present again. */
1934 if (finfo
->inotify_descr
[TRACED_DIR
] == inev
->i
.wd
1935 && ((inev
->i
.mask
& IN_DELETE_SELF
)
1936 || (inev
->i
.mask
& IN_MOVE_SELF
)
1937 || (inev
->i
.mask
& IN_IGNORED
)))
1939 bool moved
= (inev
->i
.mask
& IN_MOVE_SELF
) != 0;
1940 /* The directory watch may have already been removed
1941 but we don't know so we just remove it again and
1942 ignore the error. Then we remove the file watch.
1943 Note: watches are automatically removed for deleted
1946 inotify_rm_watch (inotify_fd
, inev
->i
.wd
);
1947 if (finfo
->inotify_descr
[TRACED_FILE
] != -1)
1949 dbg_log (_("monitored parent directory `%s` was %s, removing watch on `%s`"),
1950 finfo
->dname
, moved
? "moved" : "deleted", finfo
->fname
);
1951 if (inotify_rm_watch (inotify_fd
, finfo
->inotify_descr
[TRACED_FILE
]) < 0)
1952 dbg_log (_("failed to remove file watch `%s`: %s"),
1953 finfo
->dname
, strerror (errno
));
1955 finfo
->inotify_descr
[TRACED_FILE
] = -1;
1956 finfo
->inotify_descr
[TRACED_DIR
] = -1;
1957 to_clear
[dbcnt
] = true;
1958 if (finfo
->call_res_init
)
1960 /* Continue to the next entry since this might be the
1961 parent directory for multiple registered files and
1962 we want to remove watches for all registered files. */
1965 /* The parent directory had a create or moved to event. */
1966 if (finfo
->inotify_descr
[TRACED_DIR
] == inev
->i
.wd
1967 && ((inev
->i
.mask
& IN_MOVED_TO
)
1968 || (inev
->i
.mask
& IN_CREATE
))
1969 && strcmp (inev
->i
.name
, finfo
->sfname
) == 0)
1971 /* We detected a directory change. We look for the creation
1972 of the file we are tracking or the move of the same file
1973 into the directory. */
1975 dbg_log (_("monitored file `%s` was %s, adding watch"),
1977 inev
->i
.mask
& IN_CREATE
? "created" : "moved into place");
1978 /* File was moved in or created. Regenerate the watch. */
1979 if (finfo
->inotify_descr
[TRACED_FILE
] != -1)
1980 inotify_rm_watch (inotify_fd
,
1981 finfo
->inotify_descr
[TRACED_FILE
]);
1983 ret
= inotify_add_watch (inotify_fd
,
1987 dbg_log (_("failed to add file watch `%s`: %s"),
1988 finfo
->fname
, strerror (errno
));
1990 finfo
->inotify_descr
[TRACED_FILE
] = ret
;
1992 /* The file is new or moved so mark cache as needing to
1993 be cleared and reinitialize. */
1994 to_clear
[dbcnt
] = true;
1995 if (finfo
->call_res_init
)
1998 /* Done re-adding the watch. Don't return, we may still
1999 have other files in this same directory, same watch
2000 descriptor, and need to process them. */
2002 /* Other events are ignored, and we move on to the next file. */
2003 finfo
= finfo
->next
;
2008 /* If an entry in the array of booleans TO_CLEAR is TRUE then clear the cache
2009 for the associated database, otherwise do nothing. The TO_CLEAR array must
2010 have LASTDB entries. */
2012 clear_db_cache (bool *to_clear
)
2014 for (size_t dbcnt
= 0; dbcnt
< lastdb
; ++dbcnt
)
2015 if (to_clear
[dbcnt
])
2017 pthread_mutex_lock (&dbs
[dbcnt
].prune_lock
);
2018 dbs
[dbcnt
].clear_cache
= 1;
2019 pthread_mutex_unlock (&dbs
[dbcnt
].prune_lock
);
2020 pthread_cond_signal (&dbs
[dbcnt
].prune_cond
);
2025 handle_inotify_events (void)
2027 bool to_clear
[lastdb
] = { false, };
2030 /* Read all inotify events for files registered via
2031 register_traced_file(). */
2034 /* Potentially read multiple events into buf. */
2035 ssize_t nb
= TEMP_FAILURE_RETRY (read (inotify_fd
,
2038 if (nb
< (ssize_t
) sizeof (struct inotify_event
))
2040 /* Not even 1 event. */
2041 if (__glibc_unlikely (nb
== -1 && errno
!= EAGAIN
))
2043 /* Done reading events that are ready. */
2046 /* Process all events. The normal inotify interface delivers
2047 complete events on a read and never a partial event. */
2048 char *eptr
= &inev
.buf
[0];
2052 /* Check which of the files changed. */
2053 inotify_check_files (to_clear
, &inev
);
2054 count
= sizeof (struct inotify_event
) + inev
.i
.len
;
2057 if (nb
>= (ssize_t
) sizeof (struct inotify_event
))
2058 memcpy (&inev
, eptr
, nb
);
2064 /* Actually perform the cache clearing. */
2065 clear_db_cache (to_clear
);
2072 __attribute__ ((__noreturn__
))
2073 main_loop_poll (void)
2075 struct pollfd
*conns
= (struct pollfd
*) xmalloc (nconns
2076 * sizeof (conns
[0]));
2079 conns
[0].events
= POLLRDNORM
;
2081 size_t firstfree
= 1;
2084 if (inotify_fd
!= -1)
2086 conns
[1].fd
= inotify_fd
;
2087 conns
[1].events
= POLLRDNORM
;
2094 size_t idx_nl_status_fd
= 0;
2095 if (nl_status_fd
!= -1)
2097 idx_nl_status_fd
= nused
;
2098 conns
[nused
].fd
= nl_status_fd
;
2099 conns
[nused
].events
= POLLRDNORM
;
2107 /* Wait for any event. We wait at most a couple of seconds so
2108 that we can check whether we should close any of the accepted
2109 connections since we have not received a request. */
2110 #define MAX_ACCEPT_TIMEOUT 30
2111 #define MIN_ACCEPT_TIMEOUT 5
2112 #define MAIN_THREAD_TIMEOUT \
2113 (MAX_ACCEPT_TIMEOUT * 1000 \
2114 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * 1000 * nused) / (2 * nconns))
2116 int n
= poll (conns
, nused
, MAIN_THREAD_TIMEOUT
);
2118 time_t now
= time (NULL
);
2120 /* If there is a descriptor ready for reading or there is a new
2121 connection, process this now. */
2124 if (conns
[0].revents
!= 0)
2126 /* We have a new incoming connection. Accept the connection. */
2129 #ifndef __ASSUME_ACCEPT4
2131 if (have_accept4
>= 0)
2134 fd
= TEMP_FAILURE_RETRY (accept4 (sock
, NULL
, NULL
,
2136 #ifndef __ASSUME_ACCEPT4
2137 if (have_accept4
== 0)
2138 have_accept4
= fd
!= -1 || errno
!= ENOSYS
? 1 : -1;
2141 #ifndef __ASSUME_ACCEPT4
2142 if (have_accept4
< 0)
2143 fd
= TEMP_FAILURE_RETRY (accept (sock
, NULL
, NULL
));
2146 /* Use the descriptor if we have not reached the limit. */
2149 if (firstfree
< nconns
)
2151 conns
[firstfree
].fd
= fd
;
2152 conns
[firstfree
].events
= POLLRDNORM
;
2153 starttime
[firstfree
] = now
;
2154 if (firstfree
>= nused
)
2155 nused
= firstfree
+ 1;
2159 while (firstfree
< nused
&& conns
[firstfree
].fd
!= -1);
2162 /* We cannot use the connection so close it. */
2171 if (inotify_fd
!= -1 && conns
[1].fd
== inotify_fd
)
2173 if (conns
[1].revents
!= 0)
2176 ret
= handle_inotify_events ();
2179 /* Something went wrong when reading the inotify
2180 data. Better disable inotify. */
2181 dbg_log (_("disabled inotify-based monitoring after read error %d"), errno
);
2197 if (idx_nl_status_fd
!= 0 && conns
[idx_nl_status_fd
].revents
!= 0)
2200 /* Read all the data. We do not interpret it here. */
2201 while (TEMP_FAILURE_RETRY (read (nl_status_fd
, buf
,
2202 sizeof (buf
))) != -1)
2205 dbs
[hstdb
].head
->extra_data
[NSCD_HST_IDX_CONF_TIMESTAMP
]
2206 = __bump_nl_timestamp ();
2210 for (size_t cnt
= first
; cnt
< nused
&& n
> 0; ++cnt
)
2211 if (conns
[cnt
].revents
!= 0)
2213 fd_ready (conns
[cnt
].fd
);
2215 /* Clean up the CONNS array. */
2217 if (cnt
< firstfree
)
2219 if (cnt
== nused
- 1)
2222 while (conns
[nused
- 1].fd
== -1);
2228 /* Now find entries which have timed out. */
2231 /* We make the timeout length depend on the number of file
2232 descriptors currently used. */
2233 #define ACCEPT_TIMEOUT \
2234 (MAX_ACCEPT_TIMEOUT \
2235 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * nused) / nconns)
2236 time_t laststart
= now
- ACCEPT_TIMEOUT
;
2238 for (size_t cnt
= nused
- 1; cnt
> 0; --cnt
)
2240 if (conns
[cnt
].fd
!= -1 && starttime
[cnt
] < laststart
)
2242 /* Remove the entry, it timed out. */
2243 (void) close (conns
[cnt
].fd
);
2246 if (cnt
< firstfree
)
2248 if (cnt
== nused
- 1)
2251 while (conns
[nused
- 1].fd
== -1);
2255 if (restart_p (now
))
2263 main_loop_epoll (int efd
)
2265 struct epoll_event ev
= { 0, };
2269 /* Add the socket. */
2270 ev
.events
= EPOLLRDNORM
;
2272 if (epoll_ctl (efd
, EPOLL_CTL_ADD
, sock
, &ev
) == -1)
2273 /* We cannot use epoll. */
2276 # ifdef HAVE_INOTIFY
2277 if (inotify_fd
!= -1)
2279 ev
.events
= EPOLLRDNORM
;
2280 ev
.data
.fd
= inotify_fd
;
2281 if (epoll_ctl (efd
, EPOLL_CTL_ADD
, inotify_fd
, &ev
) == -1)
2282 /* We cannot use epoll. */
2288 # ifdef HAVE_NETLINK
2289 if (nl_status_fd
!= -1)
2291 ev
.events
= EPOLLRDNORM
;
2292 ev
.data
.fd
= nl_status_fd
;
2293 if (epoll_ctl (efd
, EPOLL_CTL_ADD
, nl_status_fd
, &ev
) == -1)
2294 /* We cannot use epoll. */
2301 struct epoll_event revs
[100];
2302 # define nrevs (sizeof (revs) / sizeof (revs[0]))
2304 int n
= epoll_wait (efd
, revs
, nrevs
, MAIN_THREAD_TIMEOUT
);
2306 time_t now
= time (NULL
);
2308 for (int cnt
= 0; cnt
< n
; ++cnt
)
2309 if (revs
[cnt
].data
.fd
== sock
)
2311 /* A new connection. */
2314 # ifndef __ASSUME_ACCEPT4
2316 if (have_accept4
>= 0)
2319 fd
= TEMP_FAILURE_RETRY (accept4 (sock
, NULL
, NULL
,
2321 # ifndef __ASSUME_ACCEPT4
2322 if (have_accept4
== 0)
2323 have_accept4
= fd
!= -1 || errno
!= ENOSYS
? 1 : -1;
2326 # ifndef __ASSUME_ACCEPT4
2327 if (have_accept4
< 0)
2328 fd
= TEMP_FAILURE_RETRY (accept (sock
, NULL
, NULL
));
2331 /* Use the descriptor if we have not reached the limit. */
2334 /* Try to add the new descriptor. */
2337 || epoll_ctl (efd
, EPOLL_CTL_ADD
, fd
, &ev
) == -1)
2338 /* The descriptor is too large or something went
2339 wrong. Close the descriptor. */
2343 /* Remember when we accepted the connection. */
2344 starttime
[fd
] = now
;
2353 # ifdef HAVE_INOTIFY
2354 else if (revs
[cnt
].data
.fd
== inotify_fd
)
2357 ret
= handle_inotify_events ();
2360 /* Something went wrong when reading the inotify
2361 data. Better disable inotify. */
2362 dbg_log (_("disabled inotify-based monitoring after read error %d"), errno
);
2363 (void) epoll_ctl (efd
, EPOLL_CTL_DEL
, inotify_fd
, NULL
);
2370 # ifdef HAVE_NETLINK
2371 else if (revs
[cnt
].data
.fd
== nl_status_fd
)
2374 /* Read all the data. We do not interpret it here. */
2375 while (TEMP_FAILURE_RETRY (read (nl_status_fd
, buf
,
2376 sizeof (buf
))) != -1)
2379 __bump_nl_timestamp ();
2384 /* Remove the descriptor from the epoll descriptor. */
2385 (void) epoll_ctl (efd
, EPOLL_CTL_DEL
, revs
[cnt
].data
.fd
, NULL
);
2387 /* Get a worker to handle the request. */
2388 fd_ready (revs
[cnt
].data
.fd
);
2390 /* Reset the time. */
2391 starttime
[revs
[cnt
].data
.fd
] = 0;
2392 if (revs
[cnt
].data
.fd
== highest
)
2395 while (highest
> 0 && starttime
[highest
] == 0);
2400 /* Now look for descriptors for accepted connections which have
2401 no reply in too long of a time. */
2402 time_t laststart
= now
- ACCEPT_TIMEOUT
;
2403 assert (starttime
[sock
] == 0);
2404 # ifdef HAVE_INOTIFY
2405 assert (inotify_fd
== -1 || starttime
[inotify_fd
] == 0);
2407 assert (nl_status_fd
== -1 || starttime
[nl_status_fd
] == 0);
2408 for (int cnt
= highest
; cnt
> STDERR_FILENO
; --cnt
)
2409 if (starttime
[cnt
] != 0 && starttime
[cnt
] < laststart
)
2411 /* We are waiting for this one for too long. Close it. */
2412 (void) epoll_ctl (efd
, EPOLL_CTL_DEL
, cnt
, NULL
);
2420 else if (cnt
!= sock
&& starttime
[cnt
] == 0 && cnt
== highest
)
2423 if (restart_p (now
))
2430 /* Start all the threads we want. The initial process is thread no. 1. */
2432 start_threads (void)
2434 /* Initialize the conditional variable we will use. The only
2435 non-standard attribute we might use is the clock selection. */
2436 pthread_condattr_t condattr
;
2437 pthread_condattr_init (&condattr
);
2439 #if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0 \
2440 && defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
2441 /* Determine whether the monotonous clock is available. */
2442 struct timespec dummy
;
2443 # if _POSIX_MONOTONIC_CLOCK == 0
2444 if (sysconf (_SC_MONOTONIC_CLOCK
) > 0)
2446 # if _POSIX_CLOCK_SELECTION == 0
2447 if (sysconf (_SC_CLOCK_SELECTION
) > 0)
2449 if (clock_getres (CLOCK_MONOTONIC
, &dummy
) == 0
2450 && pthread_condattr_setclock (&condattr
, CLOCK_MONOTONIC
) == 0)
2451 timeout_clock
= CLOCK_MONOTONIC
;
2454 /* Create the attribute for the threads. They are all created
2456 pthread_attr_init (&attr
);
2457 pthread_attr_setdetachstate (&attr
, PTHREAD_CREATE_DETACHED
);
2458 /* Use 1MB stacks, twice as much for 64-bit architectures. */
2459 pthread_attr_setstacksize (&attr
, NSCD_THREAD_STACKSIZE
);
2461 /* We allow less than LASTDB threads only for debugging. */
2462 if (debug_level
== 0)
2463 nthreads
= MAX (nthreads
, lastdb
);
2465 /* Create the threads which prune the databases. */
2466 // XXX Ideally this work would be done by some of the worker threads.
2467 // XXX But this is problematic since we would need to be able to wake
2468 // XXX them up explicitly as well as part of the group handling the
2469 // XXX ready-list. This requires an operation where we can wait on
2470 // XXX two conditional variables at the same time. This operation
2471 // XXX does not exist (yet).
2472 for (long int i
= 0; i
< lastdb
; ++i
)
2474 /* Initialize the conditional variable. */
2475 if (pthread_cond_init (&dbs
[i
].prune_cond
, &condattr
) != 0)
2477 dbg_log (_("could not initialize conditional variable"));
2478 do_exit (1, 0, NULL
);
2483 && pthread_create (&th
, &attr
, nscd_run_prune
, (void *) i
) != 0)
2485 dbg_log (_("could not start clean-up thread; terminating"));
2486 do_exit (1, 0, NULL
);
2490 pthread_condattr_destroy (&condattr
);
2492 for (long int i
= 0; i
< nthreads
; ++i
)
2495 if (pthread_create (&th
, &attr
, nscd_run_worker
, NULL
) != 0)
2499 dbg_log (_("could not start any worker thread; terminating"));
2500 do_exit (1, 0, NULL
);
2507 /* Now it is safe to let the parent know that we're doing fine and it can
2511 /* Determine how much room for descriptors we should initially
2512 allocate. This might need to change later if we cap the number
2514 const long int nfds
= sysconf (_SC_OPEN_MAX
);
2516 #define MAXCONN 16384
2517 if (nfds
== -1 || nfds
> MAXCONN
)
2519 else if (nfds
< MINCONN
)
2524 /* We need memory to pass descriptors on to the worker threads. */
2525 fdlist
= (struct fdlist
*) xcalloc (nconns
, sizeof (fdlist
[0]));
2526 /* Array to keep track when connection was accepted. */
2527 starttime
= (time_t *) xcalloc (nconns
, sizeof (starttime
[0]));
2529 /* In the main thread we execute the loop which handles incoming
2532 int efd
= epoll_create (100);
2535 main_loop_epoll (efd
);
2544 /* Look up the uid, gid, and supplementary groups to run nscd as. When
2545 this function is called, we are not listening on the nscd socket yet so
2546 we can just use the ordinary lookup functions without causing a lockup */
2548 begin_drop_privileges (void)
2550 struct passwd
*pwd
= getpwnam (server_user
);
2554 dbg_log (_("Failed to run nscd as user '%s'"), server_user
);
2555 do_exit (EXIT_FAILURE
, 0,
2556 _("Failed to run nscd as user '%s'"), server_user
);
2559 server_uid
= pwd
->pw_uid
;
2560 server_gid
= pwd
->pw_gid
;
2562 /* Save the old UID/GID if we have to change back. */
2565 old_uid
= getuid ();
2566 old_gid
= getgid ();
2569 if (getgrouplist (server_user
, server_gid
, NULL
, &server_ngroups
) == 0)
2571 /* This really must never happen. */
2572 dbg_log (_("Failed to run nscd as user '%s'"), server_user
);
2573 do_exit (EXIT_FAILURE
, errno
,
2574 _("initial getgrouplist failed"));
2577 server_groups
= (gid_t
*) xmalloc (server_ngroups
* sizeof (gid_t
));
2579 if (getgrouplist (server_user
, server_gid
, server_groups
, &server_ngroups
)
2582 dbg_log (_("Failed to run nscd as user '%s'"), server_user
);
2583 do_exit (EXIT_FAILURE
, errno
, _("getgrouplist failed"));
2588 /* Call setgroups(), setgid(), and setuid() to drop root privileges and
2589 run nscd as the user specified in the configuration file. */
2591 finish_drop_privileges (void)
2593 #if defined HAVE_LIBAUDIT && defined HAVE_LIBCAP
2594 /* We need to preserve the capabilities to connect to the audit daemon. */
2595 cap_t new_caps
= preserve_capabilities ();
2598 if (setgroups (server_ngroups
, server_groups
) == -1)
2600 dbg_log (_("Failed to run nscd as user '%s'"), server_user
);
2601 do_exit (EXIT_FAILURE
, errno
, _("setgroups failed"));
2606 res
= setresgid (server_gid
, server_gid
, old_gid
);
2608 res
= setgid (server_gid
);
2611 dbg_log (_("Failed to run nscd as user '%s'"), server_user
);
2612 do_exit (4, errno
, "setgid");
2616 res
= setresuid (server_uid
, server_uid
, old_uid
);
2618 res
= setuid (server_uid
);
2621 dbg_log (_("Failed to run nscd as user '%s'"), server_user
);
2622 do_exit (4, errno
, "setuid");
2625 #if defined HAVE_LIBAUDIT && defined HAVE_LIBCAP
2626 /* Remove the temporary capabilities. */
2627 install_real_capabilities (new_caps
);