1 /* Copyright (c) 1998-2021 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; version 2 of the License, or
8 (at your option) any later version.
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, see <https://www.gnu.org/licenses/>. */
18 /* nscd - Name Service Cache Daemon. Caches passwd, group, and hosts. */
38 #include <sys/socket.h>
48 #include "../nss/nsswitch.h"
49 #include <device-nrs.h>
51 # include <sys/inotify.h>
53 #include <kernel-features.h>
55 /* Get libc version number. */
58 #define PACKAGE _libc_intl_domainname
66 /* Running in background as daemon. */
68 /* Running in foreground but otherwise behave like a daemon,
69 i.e., detach from terminal and use syslog. This allows
70 better integration with services like systemd. */
72 /* Run in foreground in debug mode. */
76 static run_modes run_mode
= RUN_DAEMONIZE
;
78 static const char *conffile
= _PATH_NSCDCONF
;
80 static const char *print_cache
= NULL
;
84 uintptr_t pagesize_m1
;
88 time_t restart_interval
= RESTART_INTERVAL
;
93 static int check_pid (const char *file
);
94 static int write_pid (const char *file
);
95 static int monitor_child (int fd
);
97 /* Name and version of program. */
98 static void print_version (FILE *stream
, struct argp_state
*state
);
99 void (*argp_program_version_hook
) (FILE *, struct argp_state
*) = print_version
;
101 /* Function to print some extra text in the help message. */
102 static char *more_help (int key
, const char *text
, void *input
);
104 /* Definitions of arguments for argp functions. */
105 static const struct argp_option options
[] =
107 { "config-file", 'f', N_("NAME"), 0,
108 N_("Read configuration data from NAME") },
109 { "debug", 'd', NULL
, 0,
110 N_("Do not fork and display messages on the current tty") },
111 { "print", 'p', N_("NAME"), 0,
112 N_("Print contents of the offline cache file NAME") },
113 { "foreground", 'F', NULL
, 0,
114 N_("Do not fork, but otherwise behave like a daemon") },
115 { "nthreads", 't', N_("NUMBER"), 0, N_("Start NUMBER threads") },
116 { "shutdown", 'K', NULL
, 0, N_("Shut the server down") },
117 { "statistics", 'g', NULL
, 0, N_("Print current configuration statistics") },
118 { "invalidate", 'i', N_("TABLE"), 0,
119 N_("Invalidate the specified cache") },
120 { "secure", 'S', N_("TABLE,yes"), OPTION_HIDDEN
,
121 N_("Use separate cache for each user")},
122 { NULL
, 0, NULL
, 0, NULL
}
125 /* Short description of program. */
126 static const char doc
[] = N_("Name Service Cache Daemon.");
128 /* Prototype for option handler. */
129 static error_t
parse_opt (int key
, char *arg
, struct argp_state
*state
);
131 /* Data structure to communicate with argp functions. */
132 static struct argp argp
=
134 options
, parse_opt
, NULL
, doc
, NULL
, more_help
137 /* True if only statistics are requested. */
138 static bool get_stats
;
139 static int parent_fd
= -1;
142 main (int argc
, char **argv
)
146 /* Set locale via LC_ALL. */
147 setlocale (LC_ALL
, "");
148 /* Set the text message domain. */
149 textdomain (PACKAGE
);
151 /* Determine if the kernel has SELinux support. */
152 nscd_selinux_enabled (&selinux_enabled
);
154 /* Parse and process arguments. */
155 argp_parse (&argp
, argc
, argv
, 0, &remaining
, NULL
);
157 if (remaining
!= argc
)
159 error (0, 0, gettext ("wrong number of arguments"));
160 argp_help (&argp
, stdout
, ARGP_HELP_SEE
, program_invocation_short_name
);
164 /* Print the contents of the indicated cache file. */
165 if (print_cache
!= NULL
)
166 /* Does not return. */
167 nscd_print_cache (print_cache
);
169 /* Read the configuration file. */
170 if (nscd_parse_file (conffile
, dbs
) != 0)
171 /* We couldn't read the configuration file. We don't start the
173 error (EXIT_FAILURE
, 0,
174 _("failure while reading configuration file; this is fatal"));
176 /* Do we only get statistics? */
178 /* Does not return. */
179 receive_print_stats ();
181 /* Check if we are already running. */
182 if (check_pid (_PATH_NSCDPID
))
183 error (EXIT_FAILURE
, 0, _("already running"));
185 /* Remember when we started. */
186 start_time
= time (NULL
);
188 /* Determine page size. */
189 pagesize_m1
= getpagesize () - 1;
191 if (run_mode
== RUN_DAEMONIZE
|| run_mode
== RUN_FOREGROUND
)
196 /* Behave like a daemon. */
197 if (run_mode
== RUN_DAEMONIZE
)
202 error (EXIT_FAILURE
, errno
,
203 _("cannot create a pipe to talk to the child"));
207 error (EXIT_FAILURE
, errno
, _("cannot fork"));
210 /* The parent only reads from the child. */
212 exit (monitor_child (fd
[0]));
216 /* The child only writes to the parent. */
222 int nullfd
= open (_PATH_DEVNULL
, O_RDWR
);
227 if (fstat64 (nullfd
, &st
) == 0 && S_ISCHR (st
.st_mode
) != 0
228 #if defined DEV_NULL_MAJOR && defined DEV_NULL_MINOR
229 && st
.st_rdev
== makedev (DEV_NULL_MAJOR
, DEV_NULL_MINOR
)
233 /* It is the /dev/null special device alright. */
234 (void) dup2 (nullfd
, STDIN_FILENO
);
235 (void) dup2 (nullfd
, STDOUT_FILENO
);
236 (void) dup2 (nullfd
, STDERR_FILENO
);
243 /* Ugh, somebody is trying to play a trick on us. */
248 int min_close_fd
= nullfd
== -1 ? 0 : STDERR_FILENO
+ 1;
250 DIR *d
= opendir ("/proc/self/fd");
253 struct dirent64
*dirent
;
254 int dfdn
= dirfd (d
);
256 while ((dirent
= readdir64 (d
)) != NULL
)
259 long int fdn
= strtol (dirent
->d_name
, &endp
, 10);
261 if (*endp
== '\0' && fdn
!= dfdn
&& fdn
>= min_close_fd
269 for (i
= min_close_fd
; i
< getdtablesize (); i
++)
275 if (chdir ("/") != 0)
276 do_exit (EXIT_FAILURE
, errno
,
277 _("cannot change current working directory to \"/\""));
279 openlog ("nscd", LOG_CONS
| LOG_ODELAY
, LOG_DAEMON
);
281 if (write_pid (_PATH_NSCDPID
) < 0)
282 dbg_log ("%s: %s", _PATH_NSCDPID
, strerror (errno
));
284 if (!init_logfile ())
285 dbg_log (_("Could not create log file"));
287 /* Ignore job control signals. */
288 signal (SIGTTOU
, SIG_IGN
);
289 signal (SIGTTIN
, SIG_IGN
);
290 signal (SIGTSTP
, SIG_IGN
);
293 /* In debug mode we are not paranoid. */
296 signal (SIGINT
, termination_handler
);
297 signal (SIGQUIT
, termination_handler
);
298 signal (SIGTERM
, termination_handler
);
299 signal (SIGPIPE
, SIG_IGN
);
301 /* Cleanup files created by a previous 'bind'. */
302 unlink (_PATH_NSCDSOCKET
);
305 /* Use inotify to recognize changed files. */
306 inotify_fd
= inotify_init1 (IN_NONBLOCK
);
307 # ifndef __ASSUME_IN_NONBLOCK
308 if (inotify_fd
== -1 && errno
== ENOSYS
)
310 inotify_fd
= inotify_init ();
311 if (inotify_fd
!= -1)
312 fcntl (inotify_fd
, F_SETFL
, O_RDONLY
| O_NONBLOCK
);
318 /* Make sure we do not get recursive calls. */
319 __nss_disable_nscd (register_traced_file
);
322 /* Init databases. */
325 /* Start the SELinux AVC. */
329 /* Handle incoming requests */
336 static void __attribute__ ((noreturn
))
337 invalidate_db (const char *dbname
)
339 int sock
= nscd_open_socket ();
344 size_t dbname_len
= strlen (dbname
) + 1;
345 size_t reqlen
= sizeof (request_header
) + dbname_len
;
350 } *reqdata
= alloca (reqlen
);
352 reqdata
->req
.key_len
= dbname_len
;
353 reqdata
->req
.version
= NSCD_VERSION
;
354 reqdata
->req
.type
= INVALIDATE
;
355 memcpy (reqdata
->dbname
, dbname
, dbname_len
);
357 ssize_t nbytes
= TEMP_FAILURE_RETRY (send (sock
, reqdata
, reqlen
,
360 if (nbytes
!= reqlen
)
364 error (EXIT_FAILURE
, err
, _("write incomplete"));
367 /* Wait for ack. Older nscd just closed the socket when
368 prune_cache finished, silently ignore that. */
370 nbytes
= TEMP_FAILURE_RETRY (read (sock
, &resp
, sizeof (resp
)));
371 if (nbytes
!= 0 && nbytes
!= sizeof (resp
))
375 error (EXIT_FAILURE
, err
, _("cannot read invalidate ACK"));
381 error (EXIT_FAILURE
, resp
, _("invalidation failed"));
386 static void __attribute__ ((noreturn
))
389 int sock
= nscd_open_socket ();
395 req
.version
= NSCD_VERSION
;
399 ssize_t nbytes
= TEMP_FAILURE_RETRY (send (sock
, &req
, sizeof req
,
402 exit (nbytes
!= sizeof (request_header
) ? EXIT_FAILURE
: EXIT_SUCCESS
);
405 /* Handle program arguments. */
407 parse_opt (int key
, char *arg
, struct argp_state
*state
)
413 run_mode
= RUN_DEBUG
;
421 run_mode
= RUN_FOREGROUND
;
430 error (4, 0, _("Only root is allowed to use this option!"));
441 /* Validate the database name. */
444 for (cnt
= pwddb
; cnt
< lastdb
; ++cnt
)
445 if (strcmp (arg
, dbnames
[cnt
]) == 0)
450 argp_error (state
, _("'%s' is not a known database"), arg
);
455 error (4, 0, _("Only root is allowed to use this option!"));
461 nthreads
= atol (arg
);
465 error (0, 0, _("secure services not implemented anymore"));
469 return ARGP_ERR_UNKNOWN
;
475 /* Print bug-reporting information in the help message. */
477 more_help (int key
, const char *text
, void *input
)
481 case ARGP_KEY_HELP_EXTRA
:
483 /* We print some extra information. */
485 char *tables
= xstrdup (dbnames
[0]);
486 for (dbtype i
= 1; i
< lastdb
; ++i
)
489 if (asprintf (&more_tables
, "%s %s", tables
, dbnames
[i
]) < 0)
492 if (more_tables
== NULL
)
494 tables
= more_tables
;
498 if (asprintf (&tp
, gettext ("\
502 For bug reporting instructions, please see:\n\
504 "), tables
, REPORT_BUGS_TO
) < 0)
514 return (char *) text
;
517 /* Print the version information. */
519 print_version (FILE *stream
, struct argp_state
*state
)
521 fprintf (stream
, "nscd %s%s\n", PKGVERSION
, VERSION
);
522 fprintf (stream
, gettext ("\
523 Copyright (C) %s Free Software Foundation, Inc.\n\
524 This is free software; see the source for copying conditions. There is NO\n\
525 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
527 fprintf (stream
, gettext ("Written by %s.\n"),
528 "Thorsten Kukuk and Ulrich Drepper");
532 /* Create a socket connected to a name. */
534 nscd_open_socket (void)
536 struct sockaddr_un addr
;
539 sock
= socket (PF_UNIX
, SOCK_STREAM
, 0);
543 addr
.sun_family
= AF_UNIX
;
544 assert (sizeof (addr
.sun_path
) >= sizeof (_PATH_NSCDSOCKET
));
545 strcpy (addr
.sun_path
, _PATH_NSCDSOCKET
);
546 if (connect (sock
, (struct sockaddr
*) &addr
, sizeof (addr
)) < 0)
558 termination_handler (int signum
)
562 /* Clean up the file created by 'bind'. */
563 unlink (_PATH_NSCDSOCKET
);
565 /* Clean up pid file. */
566 unlink (_PATH_NSCDPID
);
568 // XXX Terminate threads.
570 /* Synchronize memory. */
571 for (int cnt
= 0; cnt
< lastdb
; ++cnt
)
573 if (!dbs
[cnt
].enabled
|| dbs
[cnt
].head
== NULL
)
576 /* Make sure nobody keeps using the database. */
577 dbs
[cnt
].head
->timestamp
= 0;
579 if (dbs
[cnt
].persistent
)
581 msync (dbs
[cnt
].head
, dbs
[cnt
].memsize
, MS_ASYNC
);
584 _exit (EXIT_SUCCESS
);
587 /* Returns 1 if the process in pid file FILE is running, 0 if not. */
589 check_pid (const char *file
)
593 fp
= fopen (file
, "r");
599 n
= fscanf (fp
, "%d", &pid
);
602 /* If we cannot parse the file default to assuming nscd runs.
603 If the PID is alive, assume it is running. That all unless
604 the PID is the same as the current process' since tha latter
605 can mean we re-exec. */
606 if ((n
!= 1 || kill (pid
, 0) == 0) && pid
!= getpid ())
613 /* Write the current process id to the file FILE.
614 Returns 0 if successful, -1 if not. */
616 write_pid (const char *file
)
620 fp
= fopen (file
, "w");
624 fprintf (fp
, "%d\n", getpid ());
626 int result
= fflush (fp
) || ferror (fp
) ? -1 : 0;
634 monitor_child (int fd
)
637 int ret
= read (fd
, &child_ret
, sizeof (child_ret
));
639 /* The child terminated with an error, either via exit or some other abnormal
640 method, like a segfault. */
641 if (ret
<= 0 || child_ret
!= 0)
644 int err
= wait (&status
);
648 fprintf (stderr
, _("'wait' failed\n"));
652 if (WIFEXITED (status
))
654 child_ret
= WEXITSTATUS (status
);
655 fprintf (stderr
, _("child exited with status %d\n"), child_ret
);
657 if (WIFSIGNALED (status
))
659 child_ret
= WTERMSIG (status
);
660 fprintf (stderr
, _("child terminated by signal %d\n"), child_ret
);
664 /* We have the child status, so exit with that code. */
671 do_exit (int child_ret
, int errnum
, const char *format
, ...)
675 int ret
__attribute__ ((unused
));
676 ret
= write (parent_fd
, &child_ret
, sizeof (child_ret
));
677 assert (ret
== sizeof (child_ret
));
683 /* Emulate error() since we don't have a va_list variant for it. */
688 fprintf (stderr
, "%s: ", program_invocation_name
);
690 va_start (argp
, format
);
691 vfprintf (stderr
, format
, argp
);
694 fprintf (stderr
, ": %s\n", strerror (errnum
));
703 notify_parent (int child_ret
)
708 int ret
__attribute__ ((unused
));
709 ret
= write (parent_fd
, &child_ret
, sizeof (child_ret
));
710 assert (ret
== sizeof (child_ret
));