1 /* Inner loops of cache daemon.
2 Copyright (C) 1998-2003, 2004, 2005, 2006 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 version 2 as
8 published by the Free Software Foundation.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
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. */
33 #include <arpa/inet.h>
35 # include <sys/epoll.h>
38 #include <sys/param.h>
41 # include <sys/sendfile.h>
43 #include <sys/socket.h>
51 # include <kernel-features.h>
55 /* Wrapper functions with error checking for standard functions. */
56 extern void *xmalloc (size_t n
);
57 extern void *xcalloc (size_t n
, size_t s
);
58 extern void *xrealloc (void *o
, size_t n
);
60 /* Support to run nscd as an unprivileged user */
61 const char *server_user
;
62 static uid_t server_uid
;
63 static gid_t server_gid
;
64 const char *stat_user
;
66 static gid_t
*server_groups
;
70 static int server_ngroups
;
72 static pthread_attr_t attr
;
74 static void begin_drop_privileges (void);
75 static void finish_drop_privileges (void);
77 /* Map request type to a string. */
78 const char *serv2str
[LASTREQ
] =
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",
89 [GETSTAT
] = "GETSTAT",
90 [INVALIDATE
] = "INVALIDATE",
91 [GETFDPW
] = "GETFDPW",
92 [GETFDGR
] = "GETFDGR",
93 [GETFDHST
] = "GETFDHST",
95 [INITGROUPS
] = "INITGROUPS"
98 /* The control data structures for the services. */
99 struct database_dyn dbs
[lastdb
] =
102 .lock
= PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
,
107 .max_db_size
= DEFAULT_MAX_DB_SIZE
,
108 .filename
= "/etc/passwd",
109 .db_filename
= _PATH_NSCD_PASSWD_DB
,
110 .disabled_iov
= &pwd_iov_disabled
,
118 .lock
= PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
,
123 .max_db_size
= DEFAULT_MAX_DB_SIZE
,
124 .filename
= "/etc/group",
125 .db_filename
= _PATH_NSCD_GROUP_DB
,
126 .disabled_iov
= &grp_iov_disabled
,
134 .lock
= PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
,
139 .max_db_size
= DEFAULT_MAX_DB_SIZE
,
140 .filename
= "/etc/hosts",
141 .db_filename
= _PATH_NSCD_HOSTS_DB
,
142 .disabled_iov
= &hst_iov_disabled
,
152 /* Mapping of request type to database. */
153 static struct database_dyn
*const serv2db
[LASTREQ
] =
155 [GETPWBYNAME
] = &dbs
[pwddb
],
156 [GETPWBYUID
] = &dbs
[pwddb
],
157 [GETGRBYNAME
] = &dbs
[grpdb
],
158 [GETGRBYGID
] = &dbs
[grpdb
],
159 [GETHOSTBYNAME
] = &dbs
[hstdb
],
160 [GETHOSTBYNAMEv6
] = &dbs
[hstdb
],
161 [GETHOSTBYADDR
] = &dbs
[hstdb
],
162 [GETHOSTBYADDRv6
] = &dbs
[hstdb
],
163 [GETFDPW
] = &dbs
[pwddb
],
164 [GETFDGR
] = &dbs
[grpdb
],
165 [GETFDHST
] = &dbs
[hstdb
],
166 [GETAI
] = &dbs
[hstdb
],
167 [INITGROUPS
] = &dbs
[grpdb
]
171 /* Number of seconds between two cache pruning runs. */
172 #define CACHE_PRUNE_INTERVAL 15
175 /* Initial number of threads to use. */
177 /* Maximum number of threads to use. */
178 int max_nthreads
= 32;
180 /* Socket for incoming connections. */
183 /* Number of times clients had to wait. */
184 unsigned long int client_queued
;
188 writeall (int fd
, const void *buf
, size_t len
)
194 ret
= TEMP_FAILURE_RETRY (send (fd
, buf
, n
, MSG_NOSIGNAL
));
197 buf
= (const char *) buf
+ ret
;
201 return ret
< 0 ? ret
: len
- n
;
207 sendfileall (int tofd
, int fromfd
, off_t off
, size_t len
)
214 ret
= TEMP_FAILURE_RETRY (sendfile (tofd
, fromfd
, &off
, n
));
220 return ret
< 0 ? ret
: len
- n
;
228 /* The following three are not really used, they are symbolic constants. */
234 use_he_begin
= use_he
| use_begin
,
235 use_he_end
= use_he
| use_end
,
238 use_key_begin
= use_key
| use_begin
,
239 use_key_end
= use_key
| use_end
,
240 use_key_first
= use_key_begin
| use_first
,
243 use_data_begin
= use_data
| use_begin
,
244 use_data_end
= use_data
| use_end
,
245 use_data_first
= use_data_begin
| use_first
250 check_use (const char *data
, nscd_ssize_t first_free
, uint8_t *usemap
,
251 enum usekey use
, ref_t start
, size_t len
)
255 if (start
> first_free
|| start
+ len
> first_free
256 || (start
& BLOCK_ALIGN_M1
))
259 if (usemap
[start
] == use_not
)
261 /* Add the start marker. */
262 usemap
[start
] = use
| use_begin
;
266 if (usemap
[++start
] != use_not
)
271 /* Add the end marker. */
272 usemap
[start
] = use
| use_end
;
274 else if ((usemap
[start
] & ~use_first
) == ((use
| use_begin
) & ~use_first
))
276 /* Hash entries can't be shared. */
280 usemap
[start
] |= (use
& use_first
);
284 if (usemap
[++start
] != use
)
287 if (usemap
[++start
] != (use
| use_end
))
291 /* Points to a wrong object or somewhere in the middle. */
298 /* Verify data in persistent database. */
300 verify_persistent_db (void *mem
, struct database_pers_head
*readhead
, int dbnr
)
302 assert (dbnr
== pwddb
|| dbnr
== grpdb
|| dbnr
== hstdb
);
304 time_t now
= time (NULL
);
306 struct database_pers_head
*head
= mem
;
307 struct database_pers_head head_copy
= *head
;
309 /* Check that the header that was read matches the head in the database. */
310 if (readhead
!= NULL
&& memcmp (head
, readhead
, sizeof (*head
)) != 0)
313 /* First some easy tests: make sure the database header is sane. */
314 if (head
->version
!= DB_VERSION
315 || head
->header_size
!= sizeof (*head
)
316 /* We allow a timestamp to be one hour ahead of the current time.
317 This should cover daylight saving time changes. */
318 || head
->timestamp
> now
+ 60 * 60 + 60
319 || (head
->gc_cycle
& 1)
320 || (size_t) head
->module
> INT32_MAX
/ sizeof (ref_t
)
321 || (size_t) head
->data_size
> INT32_MAX
- head
->module
* sizeof (ref_t
)
322 || head
->first_free
< 0
323 || head
->first_free
> head
->data_size
324 || (head
->first_free
& BLOCK_ALIGN_M1
) != 0
325 || head
->maxnentries
< 0
326 || head
->maxnsearched
< 0)
329 uint8_t *usemap
= calloc (head
->first_free
, 1);
333 const char *data
= (char *) &head
->array
[roundup (head
->module
,
334 ALIGN
/ sizeof (ref_t
))];
336 nscd_ssize_t he_cnt
= 0;
337 for (nscd_ssize_t cnt
= 0; cnt
< head
->module
; ++cnt
)
339 ref_t work
= head
->array
[cnt
];
341 while (work
!= ENDREF
)
343 if (! check_use (data
, head
->first_free
, usemap
, use_he
, work
,
344 sizeof (struct hashentry
)))
347 /* Now we know we can dereference the record. */
348 struct hashentry
*here
= (struct hashentry
*) (data
+ work
);
352 /* Make sure the record is for this type of service. */
353 if (here
->type
>= LASTREQ
354 || serv2db
[here
->type
] != &dbs
[dbnr
])
357 /* Validate boolean field value. */
358 if (here
->first
!= false && here
->first
!= true)
366 || here
->packet
> head
->first_free
367 || here
->packet
+ sizeof (struct datahead
) > head
->first_free
)
370 struct datahead
*dh
= (struct datahead
*) (data
+ here
->packet
);
372 if (! check_use (data
, head
->first_free
, usemap
,
373 use_data
| (here
->first
? use_first
: 0),
374 here
->packet
, dh
->allocsize
))
377 if (dh
->allocsize
< sizeof (struct datahead
)
378 || dh
->recsize
> dh
->allocsize
379 || (dh
->notfound
!= false && dh
->notfound
!= true)
380 || (dh
->usable
!= false && dh
->usable
!= true))
383 if (here
->key
< here
->packet
+ sizeof (struct datahead
)
384 || here
->key
> here
->packet
+ dh
->allocsize
385 || here
->key
+ here
->len
> here
->packet
+ dh
->allocsize
)
388 /* If keys can appear outside of data, this should be done
389 instead. But gc doesn't mark the data in that case. */
390 if (! check_use (data
, head
->first_free
, usemap
,
391 use_key
| (here
->first
? use_first
: 0),
392 here
->key
, here
->len
))
401 if (he_cnt
!= head
->nentries
)
404 /* See if all data and keys had at least one reference from
405 he->first == true hashentry. */
406 for (ref_t idx
= 0; idx
< head
->first_free
; ++idx
)
409 if (usemap
[idx
] == use_key_begin
)
412 if (usemap
[idx
] == use_data_begin
)
416 /* Finally, make sure the database hasn't changed since the first test. */
417 if (memcmp (mem
, &head_copy
, sizeof (*head
)) != 0)
429 /* Initialize database information structures. */
433 /* Look up unprivileged uid/gid/groups before we start listening on the
435 if (server_user
!= NULL
)
436 begin_drop_privileges ();
439 /* No configuration for this value, assume a default. */
440 nthreads
= 2 * lastdb
;
442 for (size_t cnt
= 0; cnt
< lastdb
; ++cnt
)
443 if (dbs
[cnt
].enabled
)
445 pthread_rwlock_init (&dbs
[cnt
].lock
, NULL
);
446 pthread_mutex_init (&dbs
[cnt
].memlock
, NULL
);
448 if (dbs
[cnt
].persistent
)
450 /* Try to open the appropriate file on disk. */
451 int fd
= open (dbs
[cnt
].db_filename
, O_RDWR
);
457 struct database_pers_head head
;
458 ssize_t n
= TEMP_FAILURE_RETRY (read (fd
, &head
,
460 if (n
!= sizeof (head
) || fstat64 (fd
, &st
) != 0)
463 dbg_log (_("invalid persistent database file \"%s\": %s"),
464 dbs
[cnt
].db_filename
, strerror (errno
));
465 unlink (dbs
[cnt
].db_filename
);
467 else if (head
.module
== 0 && head
.data_size
== 0)
469 /* The file has been created, but the head has not been
470 initialized yet. Remove the old file. */
471 unlink (dbs
[cnt
].db_filename
);
473 else if (head
.header_size
!= (int) sizeof (head
))
475 dbg_log (_("invalid persistent database file \"%s\": %s"),
476 dbs
[cnt
].db_filename
,
477 _("header size does not match"));
478 unlink (dbs
[cnt
].db_filename
);
480 else if ((total
= (sizeof (head
)
481 + roundup (head
.module
* sizeof (ref_t
),
485 || total
< sizeof (head
))
487 dbg_log (_("invalid persistent database file \"%s\": %s"),
488 dbs
[cnt
].db_filename
,
489 _("file size does not match"));
490 unlink (dbs
[cnt
].db_filename
);
492 /* Note we map with the maximum size allowed for the
493 database. This is likely much larger than the
494 actual file size. This is OK on most OSes since
495 extensions of the underlying file will
496 automatically translate more pages available for
498 else if ((mem
= mmap (NULL
, dbs
[cnt
].max_db_size
,
499 PROT_READ
| PROT_WRITE
,
503 else if (!verify_persistent_db (mem
, &head
, cnt
))
506 dbg_log (_("invalid persistent database file \"%s\": %s"),
507 dbs
[cnt
].db_filename
,
508 _("verification failed"));
509 unlink (dbs
[cnt
].db_filename
);
513 /* Success. We have the database. */
515 dbs
[cnt
].memsize
= total
;
516 dbs
[cnt
].data
= (char *)
517 &dbs
[cnt
].head
->array
[roundup (dbs
[cnt
].head
->module
,
518 ALIGN
/ sizeof (ref_t
))];
519 dbs
[cnt
].mmap_used
= true;
521 if (dbs
[cnt
].suggested_module
> head
.module
)
522 dbg_log (_("suggested size of table for database %s larger than the persistent database's table"),
527 /* We also need a read-only descriptor. */
530 dbs
[cnt
].ro_fd
= open (dbs
[cnt
].db_filename
, O_RDONLY
);
531 if (dbs
[cnt
].ro_fd
== -1)
533 cannot create read-only descriptor for \"%s\"; no mmap"),
534 dbs
[cnt
].db_filename
);
537 // XXX Shall we test whether the descriptors actually
538 // XXX point to the same file?
541 /* Close the file descriptors in case something went
542 wrong in which case the variable have not been
549 if (dbs
[cnt
].head
== NULL
)
551 /* No database loaded. Allocate the data structure,
553 struct database_pers_head head
;
554 size_t total
= (sizeof (head
)
555 + roundup (dbs
[cnt
].suggested_module
556 * sizeof (ref_t
), ALIGN
)
557 + (dbs
[cnt
].suggested_module
558 * DEFAULT_DATASIZE_PER_BUCKET
));
560 /* Try to create the database. If we do not need a
561 persistent database create a temporary file. */
564 if (dbs
[cnt
].persistent
)
566 fd
= open (dbs
[cnt
].db_filename
,
567 O_RDWR
| O_CREAT
| O_EXCL
| O_TRUNC
,
569 if (fd
!= -1 && dbs
[cnt
].shared
)
570 ro_fd
= open (dbs
[cnt
].db_filename
, O_RDONLY
);
574 char fname
[] = _PATH_NSCD_XYZ_DB_TMP
;
575 fd
= mkstemp (fname
);
577 /* We do not need the file name anymore after we
578 opened another file descriptor in read-only mode. */
582 ro_fd
= open (fname
, O_RDONLY
);
592 dbg_log (_("database for %s corrupted or simultaneously used; remove %s manually if necessary and restart"),
593 dbnames
[cnt
], dbs
[cnt
].db_filename
);
594 // XXX Correct way to terminate?
598 if (dbs
[cnt
].persistent
)
599 dbg_log (_("cannot create %s; no persistent database used"),
600 dbs
[cnt
].db_filename
);
602 dbg_log (_("cannot create %s; no sharing possible"),
603 dbs
[cnt
].db_filename
);
605 dbs
[cnt
].persistent
= 0;
606 // XXX remember: no mmap
610 /* Tell the user if we could not create the read-only
612 if (ro_fd
== -1 && dbs
[cnt
].shared
)
614 cannot create read-only descriptor for \"%s\"; no mmap"),
615 dbs
[cnt
].db_filename
);
617 /* Before we create the header, initialiye the hash
618 table. So that if we get interrupted if writing
619 the header we can recognize a partially initialized
621 size_t ps
= sysconf (_SC_PAGESIZE
);
623 assert (~ENDREF
== 0);
624 memset (tmpbuf
, '\xff', ps
);
626 size_t remaining
= dbs
[cnt
].suggested_module
* sizeof (ref_t
);
627 off_t offset
= sizeof (head
);
630 if (offset
% ps
!= 0)
632 towrite
= MIN (remaining
, ps
- (offset
% ps
));
633 if (pwrite (fd
, tmpbuf
, towrite
, offset
) != towrite
)
636 remaining
-= towrite
;
639 while (remaining
> ps
)
641 if (pwrite (fd
, tmpbuf
, ps
, offset
) == -1)
648 && pwrite (fd
, tmpbuf
, remaining
, offset
) != remaining
)
651 /* Create the header of the file. */
652 struct database_pers_head head
=
654 .version
= DB_VERSION
,
655 .header_size
= sizeof (head
),
656 .module
= dbs
[cnt
].suggested_module
,
657 .data_size
= (dbs
[cnt
].suggested_module
658 * DEFAULT_DATASIZE_PER_BUCKET
),
663 if ((TEMP_FAILURE_RETRY (write (fd
, &head
, sizeof (head
)))
665 || (TEMP_FAILURE_RETRY_VAL (posix_fallocate (fd
, 0, total
))
667 || (mem
= mmap (NULL
, dbs
[cnt
].max_db_size
,
668 PROT_READ
| PROT_WRITE
,
669 MAP_SHARED
, fd
, 0)) == MAP_FAILED
)
672 unlink (dbs
[cnt
].db_filename
);
673 dbg_log (_("cannot write to database file %s: %s"),
674 dbs
[cnt
].db_filename
, strerror (errno
));
675 dbs
[cnt
].persistent
= 0;
681 dbs
[cnt
].data
= (char *)
682 &dbs
[cnt
].head
->array
[roundup (dbs
[cnt
].head
->module
,
683 ALIGN
/ sizeof (ref_t
))];
684 dbs
[cnt
].memsize
= total
;
685 dbs
[cnt
].mmap_used
= true;
687 /* Remember the descriptors. */
689 dbs
[cnt
].ro_fd
= ro_fd
;
702 && ((dbs
[cnt
].wr_fd
!= -1
703 && fcntl (dbs
[cnt
].wr_fd
, F_SETFD
, FD_CLOEXEC
) == -1)
704 || (dbs
[cnt
].ro_fd
!= -1
705 && fcntl (dbs
[cnt
].ro_fd
, F_SETFD
, FD_CLOEXEC
) == -1)))
708 cannot set socket to close on exec: %s; disabling paranoia mode"),
713 if (dbs
[cnt
].head
== NULL
)
715 /* We do not use the persistent database. Just
716 create an in-memory data structure. */
717 assert (! dbs
[cnt
].persistent
);
719 dbs
[cnt
].head
= xmalloc (sizeof (struct database_pers_head
)
720 + (dbs
[cnt
].suggested_module
722 memset (dbs
[cnt
].head
, '\0', sizeof (dbs
[cnt
].head
));
723 assert (~ENDREF
== 0);
724 memset (dbs
[cnt
].head
->array
, '\xff',
725 dbs
[cnt
].suggested_module
* sizeof (ref_t
));
726 dbs
[cnt
].head
->module
= dbs
[cnt
].suggested_module
;
727 dbs
[cnt
].head
->data_size
= (DEFAULT_DATASIZE_PER_BUCKET
728 * dbs
[cnt
].head
->module
);
729 dbs
[cnt
].data
= xmalloc (dbs
[cnt
].head
->data_size
);
730 dbs
[cnt
].head
->first_free
= 0;
733 assert (dbs
[cnt
].ro_fd
== -1);
736 if (dbs
[cnt
].check_file
)
738 /* We need the modification date of the file. */
741 if (stat64 (dbs
[cnt
].filename
, &st
) < 0)
743 /* We cannot stat() the file, disable file checking. */
744 dbg_log (_("cannot stat() file `%s': %s"),
745 dbs
[cnt
].filename
, strerror (errno
));
746 dbs
[cnt
].check_file
= 0;
749 dbs
[cnt
].file_mtime
= st
.st_mtime
;
753 /* Create the socket. */
754 sock
= socket (AF_UNIX
, SOCK_STREAM
, 0);
757 dbg_log (_("cannot open socket: %s"), strerror (errno
));
758 exit (errno
== EACCES
? 4 : 1);
760 /* Bind a name to the socket. */
761 struct sockaddr_un sock_addr
;
762 sock_addr
.sun_family
= AF_UNIX
;
763 strcpy (sock_addr
.sun_path
, _PATH_NSCDSOCKET
);
764 if (bind (sock
, (struct sockaddr
*) &sock_addr
, sizeof (sock_addr
)) < 0)
766 dbg_log ("%s: %s", _PATH_NSCDSOCKET
, strerror (errno
));
767 exit (errno
== EACCES
? 4 : 1);
770 /* We don't want to get stuck on accept. */
771 int fl
= fcntl (sock
, F_GETFL
);
772 if (fl
== -1 || fcntl (sock
, F_SETFL
, fl
| O_NONBLOCK
) == -1)
774 dbg_log (_("cannot change socket to nonblocking mode: %s"),
779 /* The descriptor needs to be closed on exec. */
780 if (paranoia
&& fcntl (sock
, F_SETFD
, FD_CLOEXEC
) == -1)
782 dbg_log (_("cannot set socket to close on exec: %s"),
787 /* Set permissions for the socket. */
788 chmod (_PATH_NSCDSOCKET
, DEFFILEMODE
);
790 /* Set the socket up to accept connections. */
791 if (listen (sock
, SOMAXCONN
) < 0)
793 dbg_log (_("cannot enable socket to accept connections: %s"),
798 /* Change to unprivileged uid/gid/groups if specifed in config file */
799 if (server_user
!= NULL
)
800 finish_drop_privileges ();
804 /* Close the connections. */
813 invalidate_cache (char *key
)
817 if (strcmp (key
, "passwd") == 0)
819 else if (strcmp (key
, "group") == 0)
821 else if (__builtin_expect (strcmp (key
, "hosts"), 0) == 0)
825 /* Re-initialize the resolver. resolv.conf might have changed. */
831 if (dbs
[number
].enabled
)
832 prune_cache (&dbs
[number
], LONG_MAX
);
838 send_ro_fd (struct database_dyn
*db
, char *key
, int fd
)
840 /* If we do not have an read-only file descriptor do nothing. */
844 /* We need to send some data along with the descriptor. */
846 iov
[0].iov_base
= key
;
847 iov
[0].iov_len
= strlen (key
) + 1;
849 /* Prepare the control message to transfer the descriptor. */
853 char bytes
[CMSG_SPACE (sizeof (int))];
855 struct msghdr msg
= { .msg_iov
= iov
, .msg_iovlen
= 1,
856 .msg_control
= buf
.bytes
,
857 .msg_controllen
= sizeof (buf
) };
858 struct cmsghdr
*cmsg
= CMSG_FIRSTHDR (&msg
);
860 cmsg
->cmsg_level
= SOL_SOCKET
;
861 cmsg
->cmsg_type
= SCM_RIGHTS
;
862 cmsg
->cmsg_len
= CMSG_LEN (sizeof (int));
864 *(int *) CMSG_DATA (cmsg
) = db
->ro_fd
;
866 msg
.msg_controllen
= cmsg
->cmsg_len
;
868 /* Send the control message. We repeat when we are interrupted but
869 everything else is ignored. */
871 # define MSG_NOSIGNAL 0
873 (void) TEMP_FAILURE_RETRY (sendmsg (fd
, &msg
, MSG_NOSIGNAL
));
875 if (__builtin_expect (debug_level
> 0, 0))
876 dbg_log (_("provide access to FD %d, for %s"), db
->ro_fd
, key
);
878 #endif /* SCM_RIGHTS */
881 /* Handle new request. */
883 handle_request (int fd
, request_header
*req
, void *key
, uid_t uid
)
885 if (__builtin_expect (req
->version
, NSCD_VERSION
) != NSCD_VERSION
)
889 cannot handle old request version %d; current version is %d"),
890 req
->version
, NSCD_VERSION
);
894 /* Make the SELinux check before we go on to the standard checks. We
895 need to verify that the request type is valid, since it has not
896 yet been checked at this point. */
898 && __builtin_expect (req
->type
, GETPWBYNAME
) >= GETPWBYNAME
899 && __builtin_expect (req
->type
, LASTREQ
) < LASTREQ
900 && nscd_request_avc_has_perm (fd
, req
->type
) != 0)
903 struct database_dyn
*db
= serv2db
[req
->type
];
905 // XXX Clean up so that each new command need not introduce a
906 // XXX new conditional.
907 if ((__builtin_expect (req
->type
, GETPWBYNAME
) >= GETPWBYNAME
908 && __builtin_expect (req
->type
, LASTDBREQ
) <= LASTDBREQ
)
909 || req
->type
== GETAI
|| req
->type
== INITGROUPS
)
911 if (__builtin_expect (debug_level
, 0) > 0)
913 if (req
->type
== GETHOSTBYADDR
|| req
->type
== GETHOSTBYADDRv6
)
915 char buf
[INET6_ADDRSTRLEN
];
917 dbg_log ("\t%s (%s)", serv2str
[req
->type
],
918 inet_ntop (req
->type
== GETHOSTBYADDR
919 ? AF_INET
: AF_INET6
,
920 key
, buf
, sizeof (buf
)));
923 dbg_log ("\t%s (%s)", serv2str
[req
->type
], (char *) key
);
926 /* Is this service enabled? */
929 /* No, sent the prepared record. */
930 if (TEMP_FAILURE_RETRY (send (fd
, db
->disabled_iov
->iov_base
,
931 db
->disabled_iov
->iov_len
,
933 != (ssize_t
) db
->disabled_iov
->iov_len
934 && __builtin_expect (debug_level
, 0) > 0)
936 /* We have problems sending the result. */
938 dbg_log (_("cannot write result: %s"),
939 strerror_r (errno
, buf
, sizeof (buf
)));
945 /* Be sure we can read the data. */
946 if (__builtin_expect (pthread_rwlock_tryrdlock (&db
->lock
) != 0, 0))
948 ++db
->head
->rdlockdelayed
;
949 pthread_rwlock_rdlock (&db
->lock
);
952 /* See whether we can handle it from the cache. */
953 struct datahead
*cached
;
954 cached
= (struct datahead
*) cache_search (req
->type
, key
, req
->key_len
,
958 /* Hurray it's in the cache. */
962 if (db
->mmap_used
|| !cached
->notfound
)
964 assert (db
->wr_fd
!= -1);
965 assert ((char *) cached
->data
> (char *) db
->data
);
966 assert ((char *) cached
->data
- (char *) db
->head
968 <= (sizeof (struct database_pers_head
)
969 + db
->head
->module
* sizeof (ref_t
)
970 + db
->head
->data_size
));
971 nwritten
= sendfileall (fd
, db
->wr_fd
,
972 (char *) cached
->data
973 - (char *) db
->head
, cached
->recsize
);
974 # ifndef __ASSUME_SENDFILE
975 if (nwritten
== -1 && errno
== ENOSYS
)
980 # ifndef __ASSUME_SENDFILE
984 nwritten
= writeall (fd
, cached
->data
, cached
->recsize
);
986 if (nwritten
!= cached
->recsize
987 && __builtin_expect (debug_level
, 0) > 0)
989 /* We have problems sending the result. */
991 dbg_log (_("cannot write result: %s"),
992 strerror_r (errno
, buf
, sizeof (buf
)));
995 pthread_rwlock_unlock (&db
->lock
);
1000 pthread_rwlock_unlock (&db
->lock
);
1002 else if (__builtin_expect (debug_level
, 0) > 0)
1004 if (req
->type
== INVALIDATE
)
1005 dbg_log ("\t%s (%s)", serv2str
[req
->type
], (char *) key
);
1007 dbg_log ("\t%s", serv2str
[req
->type
]);
1010 /* Handle the request. */
1014 addpwbyname (db
, fd
, req
, key
, uid
);
1018 addpwbyuid (db
, fd
, req
, key
, uid
);
1022 addgrbyname (db
, fd
, req
, key
, uid
);
1026 addgrbygid (db
, fd
, req
, key
, uid
);
1030 addhstbyname (db
, fd
, req
, key
, uid
);
1033 case GETHOSTBYNAMEv6
:
1034 addhstbynamev6 (db
, fd
, req
, key
, uid
);
1038 addhstbyaddr (db
, fd
, req
, key
, uid
);
1041 case GETHOSTBYADDRv6
:
1042 addhstbyaddrv6 (db
, fd
, req
, key
, uid
);
1046 addhstai (db
, fd
, req
, key
, uid
);
1050 addinitgroups (db
, fd
, req
, key
, uid
);
1057 /* Get the callers credentials. */
1059 struct ucred caller
;
1060 socklen_t optlen
= sizeof (caller
);
1062 if (getsockopt (fd
, SOL_SOCKET
, SO_PEERCRED
, &caller
, &optlen
) < 0)
1066 dbg_log (_("error getting callers id: %s"),
1067 strerror_r (errno
, buf
, sizeof (buf
)));
1073 /* Some systems have no SO_PEERCRED implementation. They don't
1074 care about security so we don't as well. */
1079 /* Accept shutdown, getstat and invalidate only from root. For
1080 the stat call also allow the user specified in the config file. */
1081 if (req
->type
== GETSTAT
)
1083 if (uid
== 0 || uid
== stat_uid
)
1084 send_stats (fd
, dbs
);
1088 if (req
->type
== INVALIDATE
)
1089 invalidate_cache (key
);
1091 termination_handler (0);
1099 send_ro_fd (serv2db
[req
->type
], key
, fd
);
1104 /* Ignore the command, it's nothing we know. */
1110 /* Restart the process. */
1114 /* First determine the parameters. We do not use the parameters
1115 passed to main() since in case nscd is started by running the
1116 dynamic linker this will not work. Yes, this is not the usual
1117 case but nscd is part of glibc and we occasionally do this. */
1118 size_t buflen
= 1024;
1119 char *buf
= alloca (buflen
);
1121 int fd
= open ("/proc/self/cmdline", O_RDONLY
);
1125 cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
1134 ssize_t n
= TEMP_FAILURE_RETRY (read (fd
, buf
+ readlen
,
1139 cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
1149 if (readlen
< buflen
)
1152 /* We might have to extend the buffer. */
1153 size_t old_buflen
= buflen
;
1154 char *newp
= extend_alloca (buf
, buflen
, 2 * buflen
);
1155 buf
= memmove (newp
, buf
, old_buflen
);
1160 /* Parse the command line. Worst case scenario: every two
1161 characters form one parameter (one character plus NUL). */
1162 char **argv
= alloca ((readlen
/ 2 + 1) * sizeof (argv
[0]));
1166 while (cp
< buf
+ readlen
)
1169 cp
= (char *) rawmemchr (cp
, '\0') + 1;
1173 /* Second, change back to the old user if we changed it. */
1174 if (server_user
!= NULL
)
1176 if (setuid (old_uid
) != 0)
1179 cannot change to old UID: %s; disabling paranoia mode"),
1186 if (setgid (old_gid
) != 0)
1189 cannot change to old GID: %s; disabling paranoia mode"),
1192 setuid (server_uid
);
1198 /* Next change back to the old working directory. */
1199 if (chdir (oldcwd
) == -1)
1202 cannot change to old working directory: %s; disabling paranoia mode"),
1205 if (server_user
!= NULL
)
1207 setuid (server_uid
);
1208 setgid (server_gid
);
1214 /* Synchronize memory. */
1215 for (int cnt
= 0; cnt
< lastdb
; ++cnt
)
1217 /* Make sure nobody keeps using the database. */
1218 dbs
[cnt
].head
->timestamp
= 0;
1220 if (dbs
[cnt
].persistent
)
1222 msync (dbs
[cnt
].head
, dbs
[cnt
].memsize
, MS_ASYNC
);
1225 /* The preparations are done. */
1226 execv ("/proc/self/exe", argv
);
1228 /* If we come here, we will never be able to re-exec. */
1229 dbg_log (_("re-exec failed: %s; disabling paranoia mode"),
1232 if (server_user
!= NULL
)
1234 setuid (server_uid
);
1235 setgid (server_gid
);
1237 if (chdir ("/") != 0)
1238 dbg_log (_("cannot change current working directory to \"/\": %s"),
1244 /* List of file descriptors. */
1248 struct fdlist
*next
;
1250 /* Memory allocated for the list. */
1251 static struct fdlist
*fdlist
;
1252 /* List of currently ready-to-read file descriptors. */
1253 static struct fdlist
*readylist
;
1255 /* Conditional variable and mutex to signal availability of entries in
1256 READYLIST. The condvar is initialized dynamically since we might
1257 use a different clock depending on availability. */
1258 static pthread_cond_t readylist_cond
;
1259 static pthread_mutex_t readylist_lock
= PTHREAD_MUTEX_INITIALIZER
;
1261 /* The clock to use with the condvar. */
1262 static clockid_t timeout_clock
= CLOCK_REALTIME
;
1264 /* Number of threads ready to handle the READYLIST. */
1265 static unsigned long int nready
;
1268 /* This is the main loop. It is replicated in different threads but the
1269 `poll' call makes sure only one thread handles an incoming connection. */
1271 __attribute__ ((__noreturn__
))
1274 const long int my_number
= (long int) p
;
1275 const int run_prune
= my_number
< lastdb
&& dbs
[my_number
].enabled
;
1276 struct timespec prune_ts
;
1282 setup_thread (&dbs
[my_number
]);
1284 /* We are running. */
1285 dbs
[my_number
].head
->timestamp
= time (NULL
);
1287 if (clock_gettime (timeout_clock
, &prune_ts
) == -1)
1288 /* Should never happen. */
1291 /* Compute timeout time. */
1292 prune_ts
.tv_sec
+= CACHE_PRUNE_INTERVAL
;
1295 /* Initial locking. */
1296 pthread_mutex_lock (&readylist_lock
);
1298 /* One more thread available. */
1303 while (readylist
== NULL
)
1307 /* Wait, but not forever. */
1308 to
= pthread_cond_timedwait (&readylist_cond
, &readylist_lock
,
1311 /* If we were woken and there is no work to be done,
1312 just start pruning. */
1313 if (readylist
== NULL
&& to
== ETIMEDOUT
)
1316 pthread_mutex_unlock (&readylist_lock
);
1321 /* No need to timeout. */
1322 pthread_cond_wait (&readylist_cond
, &readylist_lock
);
1325 struct fdlist
*it
= readylist
->next
;
1326 if (readylist
->next
== readylist
)
1327 /* Just one entry on the list. */
1330 readylist
->next
= it
->next
;
1332 /* Extract the information and mark the record ready to be used
1337 /* One more thread available. */
1340 /* We are done with the list. */
1341 pthread_mutex_unlock (&readylist_lock
);
1343 /* We do not want to block on a short read or so. */
1344 int fl
= fcntl (fd
, F_GETFL
);
1345 if (fl
== -1 || fcntl (fd
, F_SETFL
, fl
| O_NONBLOCK
) == -1)
1348 /* Now read the request. */
1350 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd
, &req
, sizeof (req
)))
1351 != sizeof (req
), 0))
1353 /* We failed to read data. Note that this also might mean we
1354 failed because we would have blocked. */
1355 if (debug_level
> 0)
1356 dbg_log (_("short read while reading request: %s"),
1357 strerror_r (errno
, buf
, sizeof (buf
)));
1361 /* Check whether this is a valid request type. */
1362 if (req
.type
< GETPWBYNAME
|| req
.type
>= LASTREQ
)
1365 /* Some systems have no SO_PEERCRED implementation. They don't
1366 care about security so we don't as well. */
1371 if (__builtin_expect (debug_level
> 0, 0))
1373 struct ucred caller
;
1374 socklen_t optlen
= sizeof (caller
);
1376 if (getsockopt (fd
, SOL_SOCKET
, SO_PEERCRED
, &caller
, &optlen
) == 0)
1381 /* It should not be possible to crash the nscd with a silly
1382 request (i.e., a terribly large key). We limit the size to 1kb. */
1383 #define MAXKEYLEN 1024
1384 if (__builtin_expect (req
.key_len
, 1) < 0
1385 || __builtin_expect (req
.key_len
, 1) > MAXKEYLEN
)
1387 if (debug_level
> 0)
1388 dbg_log (_("key length in request too long: %d"), req
.key_len
);
1393 char keybuf
[MAXKEYLEN
];
1395 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd
, keybuf
,
1399 /* Again, this can also mean we would have blocked. */
1400 if (debug_level
> 0)
1401 dbg_log (_("short read while reading request key: %s"),
1402 strerror_r (errno
, buf
, sizeof (buf
)));
1406 if (__builtin_expect (debug_level
, 0) > 0)
1411 handle_request: request received (Version = %d) from PID %ld"),
1412 req
.version
, (long int) pid
);
1416 handle_request: request received (Version = %d)"), req
.version
);
1419 /* Phew, we got all the data, now process it. */
1420 handle_request (fd
, &req
, keybuf
, uid
);
1427 /* Check whether we should be pruning the cache. */
1428 assert (run_prune
|| to
== 0);
1429 if (to
== ETIMEDOUT
)
1432 /* The pthread_cond_timedwait() call timed out. It is time
1433 to clean up the cache. */
1434 assert (my_number
< lastdb
);
1435 prune_cache (&dbs
[my_number
], time (NULL
));
1437 if (clock_gettime (timeout_clock
, &prune_ts
) == -1)
1438 /* Should never happen. */
1441 /* Compute next timeout time. */
1442 prune_ts
.tv_sec
+= CACHE_PRUNE_INTERVAL
;
1444 /* In case the list is emtpy we do not want to run the prune
1445 code right away again. */
1450 pthread_mutex_lock (&readylist_lock
);
1452 /* One more thread available. */
1458 static unsigned int nconns
;
1463 pthread_mutex_lock (&readylist_lock
);
1465 /* Find an empty entry in FDLIST. */
1467 for (inner
= 0; inner
< nconns
; ++inner
)
1468 if (fdlist
[inner
].next
== NULL
)
1470 assert (inner
< nconns
);
1472 fdlist
[inner
].fd
= fd
;
1474 if (readylist
== NULL
)
1475 readylist
= fdlist
[inner
].next
= &fdlist
[inner
];
1478 fdlist
[inner
].next
= readylist
->next
;
1479 readylist
= readylist
->next
= &fdlist
[inner
];
1482 bool do_signal
= true;
1483 if (__builtin_expect (nready
== 0, 0))
1488 /* Try to start another thread to help out. */
1490 if (nthreads
< max_nthreads
1491 && pthread_create (&th
, &attr
, nscd_run
,
1492 (void *) (long int) nthreads
) == 0)
1494 /* We got another thread. */
1496 /* The new thread might need a kick. */
1502 pthread_mutex_unlock (&readylist_lock
);
1504 /* Tell one of the worker threads there is work to do. */
1506 pthread_cond_signal (&readylist_cond
);
1510 /* Check whether restarting should happen. */
1512 restart_p (time_t now
)
1514 return (paranoia
&& readylist
== NULL
&& nready
== nthreads
1515 && now
>= restart_time
);
1519 /* Array for times a connection was accepted. */
1520 static time_t *starttime
;
1524 __attribute__ ((__noreturn__
))
1525 main_loop_poll (void)
1527 struct pollfd
*conns
= (struct pollfd
*) xmalloc (nconns
1528 * sizeof (conns
[0]));
1531 conns
[0].events
= POLLRDNORM
;
1533 size_t firstfree
= 1;
1537 /* Wait for any event. We wait at most a couple of seconds so
1538 that we can check whether we should close any of the accepted
1539 connections since we have not received a request. */
1540 #define MAX_ACCEPT_TIMEOUT 30
1541 #define MIN_ACCEPT_TIMEOUT 5
1542 #define MAIN_THREAD_TIMEOUT \
1543 (MAX_ACCEPT_TIMEOUT * 1000 \
1544 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * 1000 * nused) / (2 * nconns))
1546 int n
= poll (conns
, nused
, MAIN_THREAD_TIMEOUT
);
1548 time_t now
= time (NULL
);
1550 /* If there is a descriptor ready for reading or there is a new
1551 connection, process this now. */
1554 if (conns
[0].revents
!= 0)
1556 /* We have a new incoming connection. Accept the connection. */
1557 int fd
= TEMP_FAILURE_RETRY (accept (sock
, NULL
, NULL
));
1559 /* Use the descriptor if we have not reached the limit. */
1562 if (firstfree
< nconns
)
1564 conns
[firstfree
].fd
= fd
;
1565 conns
[firstfree
].events
= POLLRDNORM
;
1566 starttime
[firstfree
] = now
;
1567 if (firstfree
>= nused
)
1568 nused
= firstfree
+ 1;
1572 while (firstfree
< nused
&& conns
[firstfree
].fd
!= -1);
1575 /* We cannot use the connection so close it. */
1582 for (size_t cnt
= 1; cnt
< nused
&& n
> 0; ++cnt
)
1583 if (conns
[cnt
].revents
!= 0)
1585 fd_ready (conns
[cnt
].fd
);
1587 /* Clean up the CONNS array. */
1589 if (cnt
< firstfree
)
1591 if (cnt
== nused
- 1)
1594 while (conns
[nused
- 1].fd
== -1);
1600 /* Now find entries which have timed out. */
1603 /* We make the timeout length depend on the number of file
1604 descriptors currently used. */
1605 #define ACCEPT_TIMEOUT \
1606 (MAX_ACCEPT_TIMEOUT \
1607 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * nused) / nconns)
1608 time_t laststart
= now
- ACCEPT_TIMEOUT
;
1610 for (size_t cnt
= nused
- 1; cnt
> 0; --cnt
)
1612 if (conns
[cnt
].fd
!= -1 && starttime
[cnt
] < laststart
)
1614 /* Remove the entry, it timed out. */
1615 (void) close (conns
[cnt
].fd
);
1618 if (cnt
< firstfree
)
1620 if (cnt
== nused
- 1)
1623 while (conns
[nused
- 1].fd
== -1);
1627 if (restart_p (now
))
1635 main_loop_epoll (int efd
)
1637 struct epoll_event ev
= { 0, };
1641 /* Add the socket. */
1642 ev
.events
= EPOLLRDNORM
;
1644 if (epoll_ctl (efd
, EPOLL_CTL_ADD
, sock
, &ev
) == -1)
1645 /* We cannot use epoll. */
1650 struct epoll_event revs
[100];
1651 # define nrevs (sizeof (revs) / sizeof (revs[0]))
1653 int n
= epoll_wait (efd
, revs
, nrevs
, MAIN_THREAD_TIMEOUT
);
1655 time_t now
= time (NULL
);
1657 for (int cnt
= 0; cnt
< n
; ++cnt
)
1658 if (revs
[cnt
].data
.fd
== sock
)
1660 /* A new connection. */
1661 int fd
= TEMP_FAILURE_RETRY (accept (sock
, NULL
, NULL
));
1665 /* Try to add the new descriptor. */
1668 || epoll_ctl (efd
, EPOLL_CTL_ADD
, fd
, &ev
) == -1)
1669 /* The descriptor is too large or something went
1670 wrong. Close the descriptor. */
1674 /* Remember when we accepted the connection. */
1675 starttime
[fd
] = now
;
1686 /* Remove the descriptor from the epoll descriptor. */
1687 (void) epoll_ctl (efd
, EPOLL_CTL_DEL
, revs
[cnt
].data
.fd
, NULL
);
1689 /* Get a worker to handle the request. */
1690 fd_ready (revs
[cnt
].data
.fd
);
1692 /* Reset the time. */
1693 starttime
[revs
[cnt
].data
.fd
] = 0;
1694 if (revs
[cnt
].data
.fd
== highest
)
1697 while (highest
> 0 && starttime
[highest
] == 0);
1702 /* Now look for descriptors for accepted connections which have
1703 no reply in too long of a time. */
1704 time_t laststart
= now
- ACCEPT_TIMEOUT
;
1705 for (int cnt
= highest
; cnt
> STDERR_FILENO
; --cnt
)
1706 if (cnt
!= sock
&& starttime
[cnt
] != 0 && starttime
[cnt
] < laststart
)
1708 /* We are waiting for this one for too long. Close it. */
1709 (void) epoll_ctl (efd
, EPOLL_CTL_DEL
, cnt
, NULL
);
1717 else if (cnt
!= sock
&& starttime
[cnt
] == 0 && cnt
== highest
)
1720 if (restart_p (now
))
1727 /* Start all the threads we want. The initial process is thread no. 1. */
1729 start_threads (void)
1731 /* Initialize the conditional variable we will use. The only
1732 non-standard attribute we might use is the clock selection. */
1733 pthread_condattr_t condattr
;
1734 pthread_condattr_init (&condattr
);
1736 #if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0 \
1737 && defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
1738 /* Determine whether the monotonous clock is available. */
1739 struct timespec dummy
;
1740 # if _POSIX_MONOTONIC_CLOCK == 0
1741 if (sysconf (_SC_MONOTONIC_CLOCK
) > 0)
1743 # if _POSIX_CLOCK_SELECTION == 0
1744 if (sysconf (_SC_CLOCK_SELECTION
) > 0)
1746 if (clock_getres (CLOCK_MONOTONIC
, &dummy
) == 0
1747 && pthread_condattr_setclock (&condattr
, CLOCK_MONOTONIC
) == 0)
1748 timeout_clock
= CLOCK_MONOTONIC
;
1751 pthread_cond_init (&readylist_cond
, &condattr
);
1752 pthread_condattr_destroy (&condattr
);
1755 /* Create the attribute for the threads. They are all created
1757 pthread_attr_init (&attr
);
1758 pthread_attr_setdetachstate (&attr
, PTHREAD_CREATE_DETACHED
);
1759 /* Use 1MB stacks, twice as much for 64-bit architectures. */
1760 pthread_attr_setstacksize (&attr
, 1024 * 1024 * (sizeof (void *) / 4));
1762 /* We allow less than LASTDB threads only for debugging. */
1763 if (debug_level
== 0)
1764 nthreads
= MAX (nthreads
, lastdb
);
1767 for (long int i
= 0; i
< nthreads
; ++i
)
1770 if (pthread_create (&th
, &attr
, nscd_run
, (void *) (i
- nfailed
)) != 0)
1773 if (nthreads
- nfailed
< lastdb
)
1775 /* We could not start enough threads. */
1776 dbg_log (_("could only start %d threads; terminating"),
1777 nthreads
- nfailed
);
1781 /* Determine how much room for descriptors we should initially
1782 allocate. This might need to change later if we cap the number
1784 const long int nfds
= sysconf (_SC_OPEN_MAX
);
1786 #define MAXCONN 16384
1787 if (nfds
== -1 || nfds
> MAXCONN
)
1789 else if (nfds
< MINCONN
)
1794 /* We need memory to pass descriptors on to the worker threads. */
1795 fdlist
= (struct fdlist
*) xcalloc (nconns
, sizeof (fdlist
[0]));
1796 /* Array to keep track when connection was accepted. */
1797 starttime
= (time_t *) xcalloc (nconns
, sizeof (starttime
[0]));
1799 /* In the main thread we execute the loop which handles incoming
1802 int efd
= epoll_create (100);
1805 main_loop_epoll (efd
);
1814 /* Look up the uid, gid, and supplementary groups to run nscd as. When
1815 this function is called, we are not listening on the nscd socket yet so
1816 we can just use the ordinary lookup functions without causing a lockup */
1818 begin_drop_privileges (void)
1820 struct passwd
*pwd
= getpwnam (server_user
);
1824 dbg_log (_("Failed to run nscd as user '%s'"), server_user
);
1825 error (EXIT_FAILURE
, 0, _("Failed to run nscd as user '%s'"),
1829 server_uid
= pwd
->pw_uid
;
1830 server_gid
= pwd
->pw_gid
;
1832 /* Save the old UID/GID if we have to change back. */
1835 old_uid
= getuid ();
1836 old_gid
= getgid ();
1839 if (getgrouplist (server_user
, server_gid
, NULL
, &server_ngroups
) == 0)
1841 /* This really must never happen. */
1842 dbg_log (_("Failed to run nscd as user '%s'"), server_user
);
1843 error (EXIT_FAILURE
, errno
, _("initial getgrouplist failed"));
1846 server_groups
= (gid_t
*) xmalloc (server_ngroups
* sizeof (gid_t
));
1848 if (getgrouplist (server_user
, server_gid
, server_groups
, &server_ngroups
)
1851 dbg_log (_("Failed to run nscd as user '%s'"), server_user
);
1852 error (EXIT_FAILURE
, errno
, _("getgrouplist failed"));
1857 /* Call setgroups(), setgid(), and setuid() to drop root privileges and
1858 run nscd as the user specified in the configuration file. */
1860 finish_drop_privileges (void)
1862 if (setgroups (server_ngroups
, server_groups
) == -1)
1864 dbg_log (_("Failed to run nscd as user '%s'"), server_user
);
1865 error (EXIT_FAILURE
, errno
, _("setgroups failed"));
1868 if (setgid (server_gid
) == -1)
1870 dbg_log (_("Failed to run nscd as user '%s'"), server_user
);
1875 if (setuid (server_uid
) == -1)
1877 dbg_log (_("Failed to run nscd as user '%s'"), server_user
);