1 /* Inner loops of cache daemon.
2 Copyright (C) 1998-2003, 2004, 2005, 2006, 2007 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 *const 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",
96 [GETSERVBYNAME
] = "GETSERVBYNAME",
97 [GETSERVBYPORT
] = "GETSERVBYPORT",
98 [GETFDSERV
] = "GETFDSERV"
101 /* The control data structures for the services. */
102 struct database_dyn dbs
[lastdb
] =
105 .lock
= PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
,
106 .prunelock
= PTHREAD_MUTEX_INITIALIZER
,
112 .max_db_size
= DEFAULT_MAX_DB_SIZE
,
114 .filename
= "/etc/passwd",
115 .db_filename
= _PATH_NSCD_PASSWD_DB
,
116 .disabled_iov
= &pwd_iov_disabled
,
124 .lock
= PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
,
125 .prunelock
= PTHREAD_MUTEX_INITIALIZER
,
131 .max_db_size
= DEFAULT_MAX_DB_SIZE
,
133 .filename
= "/etc/group",
134 .db_filename
= _PATH_NSCD_GROUP_DB
,
135 .disabled_iov
= &grp_iov_disabled
,
143 .lock
= PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
,
144 .prunelock
= PTHREAD_MUTEX_INITIALIZER
,
148 .propagate
= 0, /* Not used. */
150 .max_db_size
= DEFAULT_MAX_DB_SIZE
,
152 .filename
= "/etc/hosts",
153 .db_filename
= _PATH_NSCD_HOSTS_DB
,
154 .disabled_iov
= &hst_iov_disabled
,
162 .lock
= PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
,
163 .prunelock
= PTHREAD_MUTEX_INITIALIZER
,
167 .propagate
= 0, /* Not used. */
169 .max_db_size
= DEFAULT_MAX_DB_SIZE
,
171 .filename
= "/etc/services",
172 .db_filename
= _PATH_NSCD_SERVICES_DB
,
173 .disabled_iov
= &serv_iov_disabled
,
183 /* Mapping of request type to database. */
187 struct database_dyn
*db
;
188 } const reqinfo
[LASTREQ
] =
190 [GETPWBYNAME
] = { true, &dbs
[pwddb
] },
191 [GETPWBYUID
] = { true, &dbs
[pwddb
] },
192 [GETGRBYNAME
] = { true, &dbs
[grpdb
] },
193 [GETGRBYGID
] = { true, &dbs
[grpdb
] },
194 [GETHOSTBYNAME
] = { true, &dbs
[hstdb
] },
195 [GETHOSTBYNAMEv6
] = { true, &dbs
[hstdb
] },
196 [GETHOSTBYADDR
] = { true, &dbs
[hstdb
] },
197 [GETHOSTBYADDRv6
] = { true, &dbs
[hstdb
] },
198 [SHUTDOWN
] = { false, NULL
},
199 [GETSTAT
] = { false, NULL
},
200 [SHUTDOWN
] = { false, NULL
},
201 [GETFDPW
] = { false, &dbs
[pwddb
] },
202 [GETFDGR
] = { false, &dbs
[grpdb
] },
203 [GETFDHST
] = { false, &dbs
[hstdb
] },
204 [GETAI
] = { true, &dbs
[hstdb
] },
205 [INITGROUPS
] = { true, &dbs
[grpdb
] },
206 [GETSERVBYNAME
] = { true, &dbs
[servdb
] },
207 [GETSERVBYPORT
] = { true, &dbs
[servdb
] },
208 [GETFDSERV
] = { false, &dbs
[servdb
] }
212 /* Number of seconds between two cache pruning runs. */
213 #define CACHE_PRUNE_INTERVAL 15
216 /* Initial number of threads to use. */
218 /* Maximum number of threads to use. */
219 int max_nthreads
= 32;
221 /* Socket for incoming connections. */
224 /* Number of times clients had to wait. */
225 unsigned long int client_queued
;
229 writeall (int fd
, const void *buf
, size_t len
)
235 ret
= TEMP_FAILURE_RETRY (send (fd
, buf
, n
, MSG_NOSIGNAL
));
238 buf
= (const char *) buf
+ ret
;
242 return ret
< 0 ? ret
: len
- n
;
248 sendfileall (int tofd
, int fromfd
, off_t off
, size_t len
)
255 ret
= TEMP_FAILURE_RETRY (sendfile (tofd
, fromfd
, &off
, n
));
261 return ret
< 0 ? ret
: len
- n
;
269 /* The following three are not really used, they are symbolic constants. */
275 use_he_begin
= use_he
| use_begin
,
276 use_he_end
= use_he
| use_end
,
279 use_key_begin
= use_key
| use_begin
,
280 use_key_end
= use_key
| use_end
,
281 use_key_first
= use_key_begin
| use_first
,
284 use_data_begin
= use_data
| use_begin
,
285 use_data_end
= use_data
| use_end
,
286 use_data_first
= use_data_begin
| use_first
291 check_use (const char *data
, nscd_ssize_t first_free
, uint8_t *usemap
,
292 enum usekey use
, ref_t start
, size_t len
)
296 if (start
> first_free
|| start
+ len
> first_free
297 || (start
& BLOCK_ALIGN_M1
))
300 if (usemap
[start
] == use_not
)
302 /* Add the start marker. */
303 usemap
[start
] = use
| use_begin
;
307 if (usemap
[++start
] != use_not
)
312 /* Add the end marker. */
313 usemap
[start
] = use
| use_end
;
315 else if ((usemap
[start
] & ~use_first
) == ((use
| use_begin
) & ~use_first
))
317 /* Hash entries can't be shared. */
321 usemap
[start
] |= (use
& use_first
);
325 if (usemap
[++start
] != use
)
328 if (usemap
[++start
] != (use
| use_end
))
332 /* Points to a wrong object or somewhere in the middle. */
339 /* Verify data in persistent database. */
341 verify_persistent_db (void *mem
, struct database_pers_head
*readhead
, int dbnr
)
343 assert (dbnr
== pwddb
|| dbnr
== grpdb
|| dbnr
== hstdb
|| dbnr
== servdb
);
345 time_t now
= time (NULL
);
347 struct database_pers_head
*head
= mem
;
348 struct database_pers_head head_copy
= *head
;
350 /* Check that the header that was read matches the head in the database. */
351 if (readhead
!= NULL
&& memcmp (head
, readhead
, sizeof (*head
)) != 0)
354 /* First some easy tests: make sure the database header is sane. */
355 if (head
->version
!= DB_VERSION
356 || head
->header_size
!= sizeof (*head
)
357 /* We allow a timestamp to be one hour ahead of the current time.
358 This should cover daylight saving time changes. */
359 || head
->timestamp
> now
+ 60 * 60 + 60
360 || (head
->gc_cycle
& 1)
361 || (size_t) head
->module
> INT32_MAX
/ sizeof (ref_t
)
362 || (size_t) head
->data_size
> INT32_MAX
- head
->module
* sizeof (ref_t
)
363 || head
->first_free
< 0
364 || head
->first_free
> head
->data_size
365 || (head
->first_free
& BLOCK_ALIGN_M1
) != 0
366 || head
->maxnentries
< 0
367 || head
->maxnsearched
< 0)
370 uint8_t *usemap
= calloc (head
->first_free
, 1);
374 const char *data
= (char *) &head
->array
[roundup (head
->module
,
375 ALIGN
/ sizeof (ref_t
))];
377 nscd_ssize_t he_cnt
= 0;
378 for (nscd_ssize_t cnt
= 0; cnt
< head
->module
; ++cnt
)
380 ref_t work
= head
->array
[cnt
];
382 while (work
!= ENDREF
)
384 if (! check_use (data
, head
->first_free
, usemap
, use_he
, work
,
385 sizeof (struct hashentry
)))
388 /* Now we know we can dereference the record. */
389 struct hashentry
*here
= (struct hashentry
*) (data
+ work
);
393 /* Make sure the record is for this type of service. */
394 if (here
->type
>= LASTREQ
395 || reqinfo
[here
->type
].db
!= &dbs
[dbnr
])
398 /* Validate boolean field value. */
399 if (here
->first
!= false && here
->first
!= true)
407 || here
->packet
> head
->first_free
408 || here
->packet
+ sizeof (struct datahead
) > head
->first_free
)
411 struct datahead
*dh
= (struct datahead
*) (data
+ here
->packet
);
413 if (! check_use (data
, head
->first_free
, usemap
,
414 use_data
| (here
->first
? use_first
: 0),
415 here
->packet
, dh
->allocsize
))
418 if (dh
->allocsize
< sizeof (struct datahead
)
419 || dh
->recsize
> dh
->allocsize
420 || (dh
->notfound
!= false && dh
->notfound
!= true)
421 || (dh
->usable
!= false && dh
->usable
!= true))
424 if (here
->key
< here
->packet
+ sizeof (struct datahead
)
425 || here
->key
> here
->packet
+ dh
->allocsize
426 || here
->key
+ here
->len
> here
->packet
+ dh
->allocsize
)
429 /* If keys can appear outside of data, this should be done
430 instead. But gc doesn't mark the data in that case. */
431 if (! check_use (data
, head
->first_free
, usemap
,
432 use_key
| (here
->first
? use_first
: 0),
433 here
->key
, here
->len
))
442 if (he_cnt
!= head
->nentries
)
445 /* See if all data and keys had at least one reference from
446 he->first == true hashentry. */
447 for (ref_t idx
= 0; idx
< head
->first_free
; ++idx
)
450 if (usemap
[idx
] == use_key_begin
)
453 if (usemap
[idx
] == use_data_begin
)
457 /* Finally, make sure the database hasn't changed since the first test. */
458 if (memcmp (mem
, &head_copy
, sizeof (*head
)) != 0)
470 /* Initialize database information structures. */
474 /* Look up unprivileged uid/gid/groups before we start listening on the
476 if (server_user
!= NULL
)
477 begin_drop_privileges ();
480 /* No configuration for this value, assume a default. */
481 nthreads
= 2 * lastdb
;
483 for (size_t cnt
= 0; cnt
< lastdb
; ++cnt
)
484 if (dbs
[cnt
].enabled
)
486 pthread_rwlock_init (&dbs
[cnt
].lock
, NULL
);
487 pthread_mutex_init (&dbs
[cnt
].memlock
, NULL
);
489 if (dbs
[cnt
].persistent
)
491 /* Try to open the appropriate file on disk. */
492 int fd
= open (dbs
[cnt
].db_filename
, O_RDWR
);
498 struct database_pers_head head
;
499 ssize_t n
= TEMP_FAILURE_RETRY (read (fd
, &head
,
501 if (n
!= sizeof (head
) || fstat64 (fd
, &st
) != 0)
504 dbg_log (_("invalid persistent database file \"%s\": %s"),
505 dbs
[cnt
].db_filename
, strerror (errno
));
506 unlink (dbs
[cnt
].db_filename
);
508 else if (head
.module
== 0 && head
.data_size
== 0)
510 /* The file has been created, but the head has not been
511 initialized yet. Remove the old file. */
512 unlink (dbs
[cnt
].db_filename
);
514 else if (head
.header_size
!= (int) sizeof (head
))
516 dbg_log (_("invalid persistent database file \"%s\": %s"),
517 dbs
[cnt
].db_filename
,
518 _("header size does not match"));
519 unlink (dbs
[cnt
].db_filename
);
521 else if ((total
= (sizeof (head
)
522 + roundup (head
.module
* sizeof (ref_t
),
526 || total
< sizeof (head
))
528 dbg_log (_("invalid persistent database file \"%s\": %s"),
529 dbs
[cnt
].db_filename
,
530 _("file size does not match"));
531 unlink (dbs
[cnt
].db_filename
);
533 /* Note we map with the maximum size allowed for the
534 database. This is likely much larger than the
535 actual file size. This is OK on most OSes since
536 extensions of the underlying file will
537 automatically translate more pages available for
539 else if ((mem
= mmap (NULL
, dbs
[cnt
].max_db_size
,
540 PROT_READ
| PROT_WRITE
,
544 else if (!verify_persistent_db (mem
, &head
, cnt
))
547 dbg_log (_("invalid persistent database file \"%s\": %s"),
548 dbs
[cnt
].db_filename
,
549 _("verification failed"));
550 unlink (dbs
[cnt
].db_filename
);
554 /* Success. We have the database. */
556 dbs
[cnt
].memsize
= total
;
557 dbs
[cnt
].data
= (char *)
558 &dbs
[cnt
].head
->array
[roundup (dbs
[cnt
].head
->module
,
559 ALIGN
/ sizeof (ref_t
))];
560 dbs
[cnt
].mmap_used
= true;
562 if (dbs
[cnt
].suggested_module
> head
.module
)
563 dbg_log (_("suggested size of table for database %s larger than the persistent database's table"),
568 /* We also need a read-only descriptor. */
571 dbs
[cnt
].ro_fd
= open (dbs
[cnt
].db_filename
, O_RDONLY
);
572 if (dbs
[cnt
].ro_fd
== -1)
574 cannot create read-only descriptor for \"%s\"; no mmap"),
575 dbs
[cnt
].db_filename
);
578 // XXX Shall we test whether the descriptors actually
579 // XXX point to the same file?
582 /* Close the file descriptors in case something went
583 wrong in which case the variable have not been
590 if (dbs
[cnt
].head
== NULL
)
592 /* No database loaded. Allocate the data structure,
594 struct database_pers_head head
;
595 size_t total
= (sizeof (head
)
596 + roundup (dbs
[cnt
].suggested_module
597 * sizeof (ref_t
), ALIGN
)
598 + (dbs
[cnt
].suggested_module
599 * DEFAULT_DATASIZE_PER_BUCKET
));
601 /* Try to create the database. If we do not need a
602 persistent database create a temporary file. */
605 if (dbs
[cnt
].persistent
)
607 fd
= open (dbs
[cnt
].db_filename
,
608 O_RDWR
| O_CREAT
| O_EXCL
| O_TRUNC
,
610 if (fd
!= -1 && dbs
[cnt
].shared
)
611 ro_fd
= open (dbs
[cnt
].db_filename
, O_RDONLY
);
615 char fname
[] = _PATH_NSCD_XYZ_DB_TMP
;
616 fd
= mkstemp (fname
);
618 /* We do not need the file name anymore after we
619 opened another file descriptor in read-only mode. */
623 ro_fd
= open (fname
, O_RDONLY
);
633 dbg_log (_("database for %s corrupted or simultaneously used; remove %s manually if necessary and restart"),
634 dbnames
[cnt
], dbs
[cnt
].db_filename
);
635 // XXX Correct way to terminate?
639 if (dbs
[cnt
].persistent
)
640 dbg_log (_("cannot create %s; no persistent database used"),
641 dbs
[cnt
].db_filename
);
643 dbg_log (_("cannot create %s; no sharing possible"),
644 dbs
[cnt
].db_filename
);
646 dbs
[cnt
].persistent
= 0;
647 // XXX remember: no mmap
651 /* Tell the user if we could not create the read-only
653 if (ro_fd
== -1 && dbs
[cnt
].shared
)
655 cannot create read-only descriptor for \"%s\"; no mmap"),
656 dbs
[cnt
].db_filename
);
658 /* Before we create the header, initialiye the hash
659 table. So that if we get interrupted if writing
660 the header we can recognize a partially initialized
662 size_t ps
= sysconf (_SC_PAGESIZE
);
664 assert (~ENDREF
== 0);
665 memset (tmpbuf
, '\xff', ps
);
667 size_t remaining
= dbs
[cnt
].suggested_module
* sizeof (ref_t
);
668 off_t offset
= sizeof (head
);
671 if (offset
% ps
!= 0)
673 towrite
= MIN (remaining
, ps
- (offset
% ps
));
674 if (pwrite (fd
, tmpbuf
, towrite
, offset
) != towrite
)
677 remaining
-= towrite
;
680 while (remaining
> ps
)
682 if (pwrite (fd
, tmpbuf
, ps
, offset
) == -1)
689 && pwrite (fd
, tmpbuf
, remaining
, offset
) != remaining
)
692 /* Create the header of the file. */
693 struct database_pers_head head
=
695 .version
= DB_VERSION
,
696 .header_size
= sizeof (head
),
697 .module
= dbs
[cnt
].suggested_module
,
698 .data_size
= (dbs
[cnt
].suggested_module
699 * DEFAULT_DATASIZE_PER_BUCKET
),
704 if ((TEMP_FAILURE_RETRY (write (fd
, &head
, sizeof (head
)))
706 || (TEMP_FAILURE_RETRY_VAL (posix_fallocate (fd
, 0, total
))
708 || (mem
= mmap (NULL
, dbs
[cnt
].max_db_size
,
709 PROT_READ
| PROT_WRITE
,
710 MAP_SHARED
, fd
, 0)) == MAP_FAILED
)
713 unlink (dbs
[cnt
].db_filename
);
714 dbg_log (_("cannot write to database file %s: %s"),
715 dbs
[cnt
].db_filename
, strerror (errno
));
716 dbs
[cnt
].persistent
= 0;
722 dbs
[cnt
].data
= (char *)
723 &dbs
[cnt
].head
->array
[roundup (dbs
[cnt
].head
->module
,
724 ALIGN
/ sizeof (ref_t
))];
725 dbs
[cnt
].memsize
= total
;
726 dbs
[cnt
].mmap_used
= true;
728 /* Remember the descriptors. */
730 dbs
[cnt
].ro_fd
= ro_fd
;
743 && ((dbs
[cnt
].wr_fd
!= -1
744 && fcntl (dbs
[cnt
].wr_fd
, F_SETFD
, FD_CLOEXEC
) == -1)
745 || (dbs
[cnt
].ro_fd
!= -1
746 && fcntl (dbs
[cnt
].ro_fd
, F_SETFD
, FD_CLOEXEC
) == -1)))
749 cannot set socket to close on exec: %s; disabling paranoia mode"),
754 if (dbs
[cnt
].head
== NULL
)
756 /* We do not use the persistent database. Just
757 create an in-memory data structure. */
758 assert (! dbs
[cnt
].persistent
);
760 dbs
[cnt
].head
= xmalloc (sizeof (struct database_pers_head
)
761 + (dbs
[cnt
].suggested_module
763 memset (dbs
[cnt
].head
, '\0', sizeof (struct database_pers_head
));
764 assert (~ENDREF
== 0);
765 memset (dbs
[cnt
].head
->array
, '\xff',
766 dbs
[cnt
].suggested_module
* sizeof (ref_t
));
767 dbs
[cnt
].head
->module
= dbs
[cnt
].suggested_module
;
768 dbs
[cnt
].head
->data_size
= (DEFAULT_DATASIZE_PER_BUCKET
769 * dbs
[cnt
].head
->module
);
770 dbs
[cnt
].data
= xmalloc (dbs
[cnt
].head
->data_size
);
771 dbs
[cnt
].head
->first_free
= 0;
774 assert (dbs
[cnt
].ro_fd
== -1);
777 if (dbs
[cnt
].check_file
)
779 /* We need the modification date of the file. */
782 if (stat64 (dbs
[cnt
].filename
, &st
) < 0)
784 /* We cannot stat() the file, disable file checking. */
785 dbg_log (_("cannot stat() file `%s': %s"),
786 dbs
[cnt
].filename
, strerror (errno
));
787 dbs
[cnt
].check_file
= 0;
790 dbs
[cnt
].file_mtime
= st
.st_mtime
;
794 /* Create the socket. */
795 sock
= socket (AF_UNIX
, SOCK_STREAM
, 0);
798 dbg_log (_("cannot open socket: %s"), strerror (errno
));
799 exit (errno
== EACCES
? 4 : 1);
801 /* Bind a name to the socket. */
802 struct sockaddr_un sock_addr
;
803 sock_addr
.sun_family
= AF_UNIX
;
804 strcpy (sock_addr
.sun_path
, _PATH_NSCDSOCKET
);
805 if (bind (sock
, (struct sockaddr
*) &sock_addr
, sizeof (sock_addr
)) < 0)
807 dbg_log ("%s: %s", _PATH_NSCDSOCKET
, strerror (errno
));
808 exit (errno
== EACCES
? 4 : 1);
811 /* We don't want to get stuck on accept. */
812 int fl
= fcntl (sock
, F_GETFL
);
813 if (fl
== -1 || fcntl (sock
, F_SETFL
, fl
| O_NONBLOCK
) == -1)
815 dbg_log (_("cannot change socket to nonblocking mode: %s"),
820 /* The descriptor needs to be closed on exec. */
821 if (paranoia
&& fcntl (sock
, F_SETFD
, FD_CLOEXEC
) == -1)
823 dbg_log (_("cannot set socket to close on exec: %s"),
828 /* Set permissions for the socket. */
829 chmod (_PATH_NSCDSOCKET
, DEFFILEMODE
);
831 /* Set the socket up to accept connections. */
832 if (listen (sock
, SOMAXCONN
) < 0)
834 dbg_log (_("cannot enable socket to accept connections: %s"),
839 /* Change to unprivileged uid/gid/groups if specifed in config file */
840 if (server_user
!= NULL
)
841 finish_drop_privileges ();
845 /* Close the connections. */
854 invalidate_cache (char *key
, int fd
)
859 for (number
= pwddb
; number
< lastdb
; ++number
)
860 if (strcmp (key
, dbnames
[number
]) == 0)
862 if (dbs
[number
].reset_res
)
868 if (number
== lastdb
)
871 writeall (fd
, &resp
, sizeof (resp
));
875 if (dbs
[number
].enabled
)
876 prune_cache (&dbs
[number
], LONG_MAX
, fd
);
880 writeall (fd
, &resp
, sizeof (resp
));
887 send_ro_fd (struct database_dyn
*db
, char *key
, int fd
)
889 /* If we do not have an read-only file descriptor do nothing. */
893 /* We need to send some data along with the descriptor. */
895 iov
[0].iov_base
= key
;
896 iov
[0].iov_len
= strlen (key
) + 1;
898 /* Prepare the control message to transfer the descriptor. */
902 char bytes
[CMSG_SPACE (sizeof (int))];
904 struct msghdr msg
= { .msg_iov
= iov
, .msg_iovlen
= 1,
905 .msg_control
= buf
.bytes
,
906 .msg_controllen
= sizeof (buf
) };
907 struct cmsghdr
*cmsg
= CMSG_FIRSTHDR (&msg
);
909 cmsg
->cmsg_level
= SOL_SOCKET
;
910 cmsg
->cmsg_type
= SCM_RIGHTS
;
911 cmsg
->cmsg_len
= CMSG_LEN (sizeof (int));
913 *(int *) CMSG_DATA (cmsg
) = db
->ro_fd
;
915 msg
.msg_controllen
= cmsg
->cmsg_len
;
917 /* Send the control message. We repeat when we are interrupted but
918 everything else is ignored. */
920 # define MSG_NOSIGNAL 0
922 (void) TEMP_FAILURE_RETRY (sendmsg (fd
, &msg
, MSG_NOSIGNAL
));
924 if (__builtin_expect (debug_level
> 0, 0))
925 dbg_log (_("provide access to FD %d, for %s"), db
->ro_fd
, key
);
927 #endif /* SCM_RIGHTS */
930 /* Handle new request. */
932 handle_request (int fd
, request_header
*req
, void *key
, uid_t uid
)
934 if (__builtin_expect (req
->version
, NSCD_VERSION
) != NSCD_VERSION
)
938 cannot handle old request version %d; current version is %d"),
939 req
->version
, NSCD_VERSION
);
943 /* Make the SELinux check before we go on to the standard checks. */
944 if (selinux_enabled
&& nscd_request_avc_has_perm (fd
, req
->type
) != 0)
947 struct database_dyn
*db
= reqinfo
[req
->type
].db
;
949 /* See whether we can service the request from the cache. */
950 if (__builtin_expect (reqinfo
[req
->type
].data_request
, true))
952 if (__builtin_expect (debug_level
, 0) > 0)
954 if (req
->type
== GETHOSTBYADDR
|| req
->type
== GETHOSTBYADDRv6
)
956 char buf
[INET6_ADDRSTRLEN
];
958 dbg_log ("\t%s (%s)", serv2str
[req
->type
],
959 inet_ntop (req
->type
== GETHOSTBYADDR
960 ? AF_INET
: AF_INET6
,
961 key
, buf
, sizeof (buf
)));
964 dbg_log ("\t%s (%s)", serv2str
[req
->type
], (char *) key
);
967 /* Is this service enabled? */
968 if (__builtin_expect (!db
->enabled
, 0))
970 /* No, sent the prepared record. */
971 if (TEMP_FAILURE_RETRY (send (fd
, db
->disabled_iov
->iov_base
,
972 db
->disabled_iov
->iov_len
,
974 != (ssize_t
) db
->disabled_iov
->iov_len
975 && __builtin_expect (debug_level
, 0) > 0)
977 /* We have problems sending the result. */
979 dbg_log (_("cannot write result: %s"),
980 strerror_r (errno
, buf
, sizeof (buf
)));
986 /* Be sure we can read the data. */
987 if (__builtin_expect (pthread_rwlock_tryrdlock (&db
->lock
) != 0, 0))
989 ++db
->head
->rdlockdelayed
;
990 pthread_rwlock_rdlock (&db
->lock
);
993 /* See whether we can handle it from the cache. */
994 struct datahead
*cached
;
995 cached
= (struct datahead
*) cache_search (req
->type
, key
, req
->key_len
,
999 /* Hurray it's in the cache. */
1002 #ifdef HAVE_SENDFILE
1003 if (db
->mmap_used
|| !cached
->notfound
)
1005 assert (db
->wr_fd
!= -1);
1006 assert ((char *) cached
->data
> (char *) db
->data
);
1007 assert ((char *) cached
->data
- (char *) db
->head
1009 <= (sizeof (struct database_pers_head
)
1010 + db
->head
->module
* sizeof (ref_t
)
1011 + db
->head
->data_size
));
1012 nwritten
= sendfileall (fd
, db
->wr_fd
,
1013 (char *) cached
->data
1014 - (char *) db
->head
, cached
->recsize
);
1015 # ifndef __ASSUME_SENDFILE
1016 if (nwritten
== -1 && errno
== ENOSYS
)
1021 # ifndef __ASSUME_SENDFILE
1025 nwritten
= writeall (fd
, cached
->data
, cached
->recsize
);
1027 if (nwritten
!= cached
->recsize
1028 && __builtin_expect (debug_level
, 0) > 0)
1030 /* We have problems sending the result. */
1032 dbg_log (_("cannot write result: %s"),
1033 strerror_r (errno
, buf
, sizeof (buf
)));
1036 pthread_rwlock_unlock (&db
->lock
);
1041 pthread_rwlock_unlock (&db
->lock
);
1043 else if (__builtin_expect (debug_level
, 0) > 0)
1045 if (req
->type
== INVALIDATE
)
1046 dbg_log ("\t%s (%s)", serv2str
[req
->type
], (char *) key
);
1048 dbg_log ("\t%s", serv2str
[req
->type
]);
1051 /* Handle the request. */
1055 addpwbyname (db
, fd
, req
, key
, uid
);
1059 addpwbyuid (db
, fd
, req
, key
, uid
);
1063 addgrbyname (db
, fd
, req
, key
, uid
);
1067 addgrbygid (db
, fd
, req
, key
, uid
);
1071 addhstbyname (db
, fd
, req
, key
, uid
);
1074 case GETHOSTBYNAMEv6
:
1075 addhstbynamev6 (db
, fd
, req
, key
, uid
);
1079 addhstbyaddr (db
, fd
, req
, key
, uid
);
1082 case GETHOSTBYADDRv6
:
1083 addhstbyaddrv6 (db
, fd
, req
, key
, uid
);
1087 addhstai (db
, fd
, req
, key
, uid
);
1091 addinitgroups (db
, fd
, req
, key
, uid
);
1095 addservbyname (db
, fd
, req
, key
, uid
);
1099 addservbyport (db
, fd
, req
, key
, uid
);
1106 /* Get the callers credentials. */
1108 struct ucred caller
;
1109 socklen_t optlen
= sizeof (caller
);
1111 if (getsockopt (fd
, SOL_SOCKET
, SO_PEERCRED
, &caller
, &optlen
) < 0)
1115 dbg_log (_("error getting caller's id: %s"),
1116 strerror_r (errno
, buf
, sizeof (buf
)));
1122 /* Some systems have no SO_PEERCRED implementation. They don't
1123 care about security so we don't as well. */
1128 /* Accept shutdown, getstat and invalidate only from root. For
1129 the stat call also allow the user specified in the config file. */
1130 if (req
->type
== GETSTAT
)
1132 if (uid
== 0 || uid
== stat_uid
)
1133 send_stats (fd
, dbs
);
1137 if (req
->type
== INVALIDATE
)
1138 invalidate_cache (key
, fd
);
1140 termination_handler (0);
1149 send_ro_fd (reqinfo
[req
->type
].db
, key
, fd
);
1154 /* Ignore the command, it's nothing we know. */
1160 /* Restart the process. */
1164 /* First determine the parameters. We do not use the parameters
1165 passed to main() since in case nscd is started by running the
1166 dynamic linker this will not work. Yes, this is not the usual
1167 case but nscd is part of glibc and we occasionally do this. */
1168 size_t buflen
= 1024;
1169 char *buf
= alloca (buflen
);
1171 int fd
= open ("/proc/self/cmdline", O_RDONLY
);
1175 cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
1184 ssize_t n
= TEMP_FAILURE_RETRY (read (fd
, buf
+ readlen
,
1189 cannot read /proc/self/cmdline: %s; disabling paranoia mode"),
1199 if (readlen
< buflen
)
1202 /* We might have to extend the buffer. */
1203 size_t old_buflen
= buflen
;
1204 char *newp
= extend_alloca (buf
, buflen
, 2 * buflen
);
1205 buf
= memmove (newp
, buf
, old_buflen
);
1210 /* Parse the command line. Worst case scenario: every two
1211 characters form one parameter (one character plus NUL). */
1212 char **argv
= alloca ((readlen
/ 2 + 1) * sizeof (argv
[0]));
1216 while (cp
< buf
+ readlen
)
1219 cp
= (char *) rawmemchr (cp
, '\0') + 1;
1223 /* Second, change back to the old user if we changed it. */
1224 if (server_user
!= NULL
)
1226 if (setresuid (old_uid
, old_uid
, old_uid
) != 0)
1229 cannot change to old UID: %s; disabling paranoia mode"),
1236 if (setresgid (old_gid
, old_gid
, old_gid
) != 0)
1239 cannot change to old GID: %s; disabling paranoia mode"),
1242 setuid (server_uid
);
1248 /* Next change back to the old working directory. */
1249 if (chdir (oldcwd
) == -1)
1252 cannot change to old working directory: %s; disabling paranoia mode"),
1255 if (server_user
!= NULL
)
1257 setuid (server_uid
);
1258 setgid (server_gid
);
1264 /* Synchronize memory. */
1265 for (int cnt
= 0; cnt
< lastdb
; ++cnt
)
1267 /* Make sure nobody keeps using the database. */
1268 dbs
[cnt
].head
->timestamp
= 0;
1270 if (dbs
[cnt
].persistent
)
1272 msync (dbs
[cnt
].head
, dbs
[cnt
].memsize
, MS_ASYNC
);
1275 /* The preparations are done. */
1276 execv ("/proc/self/exe", argv
);
1278 /* If we come here, we will never be able to re-exec. */
1279 dbg_log (_("re-exec failed: %s; disabling paranoia mode"),
1282 if (server_user
!= NULL
)
1284 setuid (server_uid
);
1285 setgid (server_gid
);
1287 if (chdir ("/") != 0)
1288 dbg_log (_("cannot change current working directory to \"/\": %s"),
1294 /* List of file descriptors. */
1298 struct fdlist
*next
;
1300 /* Memory allocated for the list. */
1301 static struct fdlist
*fdlist
;
1302 /* List of currently ready-to-read file descriptors. */
1303 static struct fdlist
*readylist
;
1305 /* Conditional variable and mutex to signal availability of entries in
1306 READYLIST. The condvar is initialized dynamically since we might
1307 use a different clock depending on availability. */
1308 static pthread_cond_t readylist_cond
;
1309 static pthread_mutex_t readylist_lock
= PTHREAD_MUTEX_INITIALIZER
;
1311 /* The clock to use with the condvar. */
1312 static clockid_t timeout_clock
= CLOCK_REALTIME
;
1314 /* Number of threads ready to handle the READYLIST. */
1315 static unsigned long int nready
;
1318 /* This is the main loop. It is replicated in different threads but the
1319 `poll' call makes sure only one thread handles an incoming connection. */
1321 __attribute__ ((__noreturn__
))
1324 const long int my_number
= (long int) p
;
1325 const int run_prune
= my_number
< lastdb
&& dbs
[my_number
].enabled
;
1326 struct timespec prune_ts
;
1332 setup_thread (&dbs
[my_number
]);
1334 /* We are running. */
1335 dbs
[my_number
].head
->timestamp
= time (NULL
);
1337 if (clock_gettime (timeout_clock
, &prune_ts
) == -1)
1338 /* Should never happen. */
1341 /* Compute timeout time. */
1342 prune_ts
.tv_sec
+= CACHE_PRUNE_INTERVAL
;
1345 /* Initial locking. */
1346 pthread_mutex_lock (&readylist_lock
);
1348 /* One more thread available. */
1353 while (readylist
== NULL
)
1357 /* Wait, but not forever. */
1358 to
= pthread_cond_timedwait (&readylist_cond
, &readylist_lock
,
1361 /* If we were woken and there is no work to be done,
1362 just start pruning. */
1363 if (readylist
== NULL
&& to
== ETIMEDOUT
)
1366 pthread_mutex_unlock (&readylist_lock
);
1371 /* No need to timeout. */
1372 pthread_cond_wait (&readylist_cond
, &readylist_lock
);
1375 struct fdlist
*it
= readylist
->next
;
1376 if (readylist
->next
== readylist
)
1377 /* Just one entry on the list. */
1380 readylist
->next
= it
->next
;
1382 /* Extract the information and mark the record ready to be used
1387 /* One more thread available. */
1390 /* We are done with the list. */
1391 pthread_mutex_unlock (&readylist_lock
);
1393 /* We do not want to block on a short read or so. */
1394 int fl
= fcntl (fd
, F_GETFL
);
1395 if (fl
== -1 || fcntl (fd
, F_SETFL
, fl
| O_NONBLOCK
) == -1)
1398 /* Now read the request. */
1400 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd
, &req
, sizeof (req
)))
1401 != sizeof (req
), 0))
1403 /* We failed to read data. Note that this also might mean we
1404 failed because we would have blocked. */
1405 if (debug_level
> 0)
1406 dbg_log (_("short read while reading request: %s"),
1407 strerror_r (errno
, buf
, sizeof (buf
)));
1411 /* Check whether this is a valid request type. */
1412 if (req
.type
< GETPWBYNAME
|| req
.type
>= LASTREQ
)
1415 /* Some systems have no SO_PEERCRED implementation. They don't
1416 care about security so we don't as well. */
1421 if (__builtin_expect (debug_level
> 0, 0))
1423 struct ucred caller
;
1424 socklen_t optlen
= sizeof (caller
);
1426 if (getsockopt (fd
, SOL_SOCKET
, SO_PEERCRED
, &caller
, &optlen
) == 0)
1431 /* It should not be possible to crash the nscd with a silly
1432 request (i.e., a terribly large key). We limit the size to 1kb. */
1433 if (__builtin_expect (req
.key_len
, 1) < 0
1434 || __builtin_expect (req
.key_len
, 1) > MAXKEYLEN
)
1436 if (debug_level
> 0)
1437 dbg_log (_("key length in request too long: %d"), req
.key_len
);
1442 char keybuf
[MAXKEYLEN
];
1444 if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd
, keybuf
,
1448 /* Again, this can also mean we would have blocked. */
1449 if (debug_level
> 0)
1450 dbg_log (_("short read while reading request key: %s"),
1451 strerror_r (errno
, buf
, sizeof (buf
)));
1455 if (__builtin_expect (debug_level
, 0) > 0)
1460 handle_request: request received (Version = %d) from PID %ld"),
1461 req
.version
, (long int) pid
);
1465 handle_request: request received (Version = %d)"), req
.version
);
1468 /* Phew, we got all the data, now process it. */
1469 handle_request (fd
, &req
, keybuf
, uid
);
1476 /* Check whether we should be pruning the cache. */
1477 assert (run_prune
|| to
== 0);
1478 if (to
== ETIMEDOUT
)
1481 /* The pthread_cond_timedwait() call timed out. It is time
1482 to clean up the cache. */
1483 assert (my_number
< lastdb
);
1484 prune_cache (&dbs
[my_number
], time (NULL
), -1);
1486 if (clock_gettime (timeout_clock
, &prune_ts
) == -1)
1487 /* Should never happen. */
1490 /* Compute next timeout time. */
1491 prune_ts
.tv_sec
+= CACHE_PRUNE_INTERVAL
;
1493 /* In case the list is emtpy we do not want to run the prune
1494 code right away again. */
1499 pthread_mutex_lock (&readylist_lock
);
1501 /* One more thread available. */
1507 static unsigned int nconns
;
1512 pthread_mutex_lock (&readylist_lock
);
1514 /* Find an empty entry in FDLIST. */
1516 for (inner
= 0; inner
< nconns
; ++inner
)
1517 if (fdlist
[inner
].next
== NULL
)
1519 assert (inner
< nconns
);
1521 fdlist
[inner
].fd
= fd
;
1523 if (readylist
== NULL
)
1524 readylist
= fdlist
[inner
].next
= &fdlist
[inner
];
1527 fdlist
[inner
].next
= readylist
->next
;
1528 readylist
= readylist
->next
= &fdlist
[inner
];
1531 bool do_signal
= true;
1532 if (__builtin_expect (nready
== 0, 0))
1537 /* Try to start another thread to help out. */
1539 if (nthreads
< max_nthreads
1540 && pthread_create (&th
, &attr
, nscd_run
,
1541 (void *) (long int) nthreads
) == 0)
1543 /* We got another thread. */
1545 /* The new thread might need a kick. */
1551 pthread_mutex_unlock (&readylist_lock
);
1553 /* Tell one of the worker threads there is work to do. */
1555 pthread_cond_signal (&readylist_cond
);
1559 /* Check whether restarting should happen. */
1561 restart_p (time_t now
)
1563 return (paranoia
&& readylist
== NULL
&& nready
== nthreads
1564 && now
>= restart_time
);
1568 /* Array for times a connection was accepted. */
1569 static time_t *starttime
;
1573 __attribute__ ((__noreturn__
))
1574 main_loop_poll (void)
1576 struct pollfd
*conns
= (struct pollfd
*) xmalloc (nconns
1577 * sizeof (conns
[0]));
1580 conns
[0].events
= POLLRDNORM
;
1582 size_t firstfree
= 1;
1586 /* Wait for any event. We wait at most a couple of seconds so
1587 that we can check whether we should close any of the accepted
1588 connections since we have not received a request. */
1589 #define MAX_ACCEPT_TIMEOUT 30
1590 #define MIN_ACCEPT_TIMEOUT 5
1591 #define MAIN_THREAD_TIMEOUT \
1592 (MAX_ACCEPT_TIMEOUT * 1000 \
1593 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * 1000 * nused) / (2 * nconns))
1595 int n
= poll (conns
, nused
, MAIN_THREAD_TIMEOUT
);
1597 time_t now
= time (NULL
);
1599 /* If there is a descriptor ready for reading or there is a new
1600 connection, process this now. */
1603 if (conns
[0].revents
!= 0)
1605 /* We have a new incoming connection. Accept the connection. */
1606 int fd
= TEMP_FAILURE_RETRY (accept (sock
, NULL
, NULL
));
1608 /* Use the descriptor if we have not reached the limit. */
1611 if (firstfree
< nconns
)
1613 conns
[firstfree
].fd
= fd
;
1614 conns
[firstfree
].events
= POLLRDNORM
;
1615 starttime
[firstfree
] = now
;
1616 if (firstfree
>= nused
)
1617 nused
= firstfree
+ 1;
1621 while (firstfree
< nused
&& conns
[firstfree
].fd
!= -1);
1624 /* We cannot use the connection so close it. */
1631 for (size_t cnt
= 1; cnt
< nused
&& n
> 0; ++cnt
)
1632 if (conns
[cnt
].revents
!= 0)
1634 fd_ready (conns
[cnt
].fd
);
1636 /* Clean up the CONNS array. */
1638 if (cnt
< firstfree
)
1640 if (cnt
== nused
- 1)
1643 while (conns
[nused
- 1].fd
== -1);
1649 /* Now find entries which have timed out. */
1652 /* We make the timeout length depend on the number of file
1653 descriptors currently used. */
1654 #define ACCEPT_TIMEOUT \
1655 (MAX_ACCEPT_TIMEOUT \
1656 - ((MAX_ACCEPT_TIMEOUT - MIN_ACCEPT_TIMEOUT) * nused) / nconns)
1657 time_t laststart
= now
- ACCEPT_TIMEOUT
;
1659 for (size_t cnt
= nused
- 1; cnt
> 0; --cnt
)
1661 if (conns
[cnt
].fd
!= -1 && starttime
[cnt
] < laststart
)
1663 /* Remove the entry, it timed out. */
1664 (void) close (conns
[cnt
].fd
);
1667 if (cnt
< firstfree
)
1669 if (cnt
== nused
- 1)
1672 while (conns
[nused
- 1].fd
== -1);
1676 if (restart_p (now
))
1684 main_loop_epoll (int efd
)
1686 struct epoll_event ev
= { 0, };
1690 /* Add the socket. */
1691 ev
.events
= EPOLLRDNORM
;
1693 if (epoll_ctl (efd
, EPOLL_CTL_ADD
, sock
, &ev
) == -1)
1694 /* We cannot use epoll. */
1699 struct epoll_event revs
[100];
1700 # define nrevs (sizeof (revs) / sizeof (revs[0]))
1702 int n
= epoll_wait (efd
, revs
, nrevs
, MAIN_THREAD_TIMEOUT
);
1704 time_t now
= time (NULL
);
1706 for (int cnt
= 0; cnt
< n
; ++cnt
)
1707 if (revs
[cnt
].data
.fd
== sock
)
1709 /* A new connection. */
1710 int fd
= TEMP_FAILURE_RETRY (accept (sock
, NULL
, NULL
));
1714 /* Try to add the new descriptor. */
1717 || epoll_ctl (efd
, EPOLL_CTL_ADD
, fd
, &ev
) == -1)
1718 /* The descriptor is too large or something went
1719 wrong. Close the descriptor. */
1723 /* Remember when we accepted the connection. */
1724 starttime
[fd
] = now
;
1735 /* Remove the descriptor from the epoll descriptor. */
1736 (void) epoll_ctl (efd
, EPOLL_CTL_DEL
, revs
[cnt
].data
.fd
, NULL
);
1738 /* Get a worker to handle the request. */
1739 fd_ready (revs
[cnt
].data
.fd
);
1741 /* Reset the time. */
1742 starttime
[revs
[cnt
].data
.fd
] = 0;
1743 if (revs
[cnt
].data
.fd
== highest
)
1746 while (highest
> 0 && starttime
[highest
] == 0);
1751 /* Now look for descriptors for accepted connections which have
1752 no reply in too long of a time. */
1753 time_t laststart
= now
- ACCEPT_TIMEOUT
;
1754 for (int cnt
= highest
; cnt
> STDERR_FILENO
; --cnt
)
1755 if (cnt
!= sock
&& starttime
[cnt
] != 0 && starttime
[cnt
] < laststart
)
1757 /* We are waiting for this one for too long. Close it. */
1758 (void) epoll_ctl (efd
, EPOLL_CTL_DEL
, cnt
, NULL
);
1766 else if (cnt
!= sock
&& starttime
[cnt
] == 0 && cnt
== highest
)
1769 if (restart_p (now
))
1776 /* Start all the threads we want. The initial process is thread no. 1. */
1778 start_threads (void)
1780 /* Initialize the conditional variable we will use. The only
1781 non-standard attribute we might use is the clock selection. */
1782 pthread_condattr_t condattr
;
1783 pthread_condattr_init (&condattr
);
1785 #if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0 \
1786 && defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
1787 /* Determine whether the monotonous clock is available. */
1788 struct timespec dummy
;
1789 # if _POSIX_MONOTONIC_CLOCK == 0
1790 if (sysconf (_SC_MONOTONIC_CLOCK
) > 0)
1792 # if _POSIX_CLOCK_SELECTION == 0
1793 if (sysconf (_SC_CLOCK_SELECTION
) > 0)
1795 if (clock_getres (CLOCK_MONOTONIC
, &dummy
) == 0
1796 && pthread_condattr_setclock (&condattr
, CLOCK_MONOTONIC
) == 0)
1797 timeout_clock
= CLOCK_MONOTONIC
;
1800 pthread_cond_init (&readylist_cond
, &condattr
);
1801 pthread_condattr_destroy (&condattr
);
1804 /* Create the attribute for the threads. They are all created
1806 pthread_attr_init (&attr
);
1807 pthread_attr_setdetachstate (&attr
, PTHREAD_CREATE_DETACHED
);
1808 /* Use 1MB stacks, twice as much for 64-bit architectures. */
1809 pthread_attr_setstacksize (&attr
, 1024 * 1024 * (sizeof (void *) / 4));
1811 /* We allow less than LASTDB threads only for debugging. */
1812 if (debug_level
== 0)
1813 nthreads
= MAX (nthreads
, lastdb
);
1816 for (long int i
= 0; i
< nthreads
; ++i
)
1819 if (pthread_create (&th
, &attr
, nscd_run
, (void *) (i
- nfailed
)) != 0)
1822 if (nthreads
- nfailed
< lastdb
)
1824 /* We could not start enough threads. */
1825 dbg_log (_("could only start %d threads; terminating"),
1826 nthreads
- nfailed
);
1830 /* Determine how much room for descriptors we should initially
1831 allocate. This might need to change later if we cap the number
1833 const long int nfds
= sysconf (_SC_OPEN_MAX
);
1835 #define MAXCONN 16384
1836 if (nfds
== -1 || nfds
> MAXCONN
)
1838 else if (nfds
< MINCONN
)
1843 /* We need memory to pass descriptors on to the worker threads. */
1844 fdlist
= (struct fdlist
*) xcalloc (nconns
, sizeof (fdlist
[0]));
1845 /* Array to keep track when connection was accepted. */
1846 starttime
= (time_t *) xcalloc (nconns
, sizeof (starttime
[0]));
1848 /* In the main thread we execute the loop which handles incoming
1851 int efd
= epoll_create (100);
1854 main_loop_epoll (efd
);
1863 /* Look up the uid, gid, and supplementary groups to run nscd as. When
1864 this function is called, we are not listening on the nscd socket yet so
1865 we can just use the ordinary lookup functions without causing a lockup */
1867 begin_drop_privileges (void)
1869 struct passwd
*pwd
= getpwnam (server_user
);
1873 dbg_log (_("Failed to run nscd as user '%s'"), server_user
);
1874 error (EXIT_FAILURE
, 0, _("Failed to run nscd as user '%s'"),
1878 server_uid
= pwd
->pw_uid
;
1879 server_gid
= pwd
->pw_gid
;
1881 /* Save the old UID/GID if we have to change back. */
1884 old_uid
= getuid ();
1885 old_gid
= getgid ();
1888 if (getgrouplist (server_user
, server_gid
, NULL
, &server_ngroups
) == 0)
1890 /* This really must never happen. */
1891 dbg_log (_("Failed to run nscd as user '%s'"), server_user
);
1892 error (EXIT_FAILURE
, errno
, _("initial getgrouplist failed"));
1895 server_groups
= (gid_t
*) xmalloc (server_ngroups
* sizeof (gid_t
));
1897 if (getgrouplist (server_user
, server_gid
, server_groups
, &server_ngroups
)
1900 dbg_log (_("Failed to run nscd as user '%s'"), server_user
);
1901 error (EXIT_FAILURE
, errno
, _("getgrouplist failed"));
1906 /* Call setgroups(), setgid(), and setuid() to drop root privileges and
1907 run nscd as the user specified in the configuration file. */
1909 finish_drop_privileges (void)
1911 #if defined HAVE_LIBAUDIT && defined HAVE_LIBCAP
1912 /* We need to preserve the capabilities to connect to the audit daemon. */
1913 cap_t new_caps
= preserve_capabilities ();
1916 if (setgroups (server_ngroups
, server_groups
) == -1)
1918 dbg_log (_("Failed to run nscd as user '%s'"), server_user
);
1919 error (EXIT_FAILURE
, errno
, _("setgroups failed"));
1924 res
= setresgid (server_gid
, server_gid
, old_gid
);
1926 res
= setgid (server_gid
);
1929 dbg_log (_("Failed to run nscd as user '%s'"), server_user
);
1935 res
= setresuid (server_uid
, server_uid
, old_uid
);
1937 res
= setuid (server_uid
);
1940 dbg_log (_("Failed to run nscd as user '%s'"), server_user
);
1945 #if defined HAVE_LIBAUDIT && defined HAVE_LIBCAP
1946 /* Remove the temporary capabilities. */
1947 install_real_capabilities (new_caps
);