Update x86_64 ULPs (AMD Family 10h)
[jlayton/glibc.git] / nscd / nscd.c
1 /* Copyright (c) 1998-2014 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
4
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.
9
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.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, see <http://www.gnu.org/licenses/>.  */
17
18 /* nscd - Name Service Cache Daemon. Caches passwd, group, and hosts.  */
19
20 #include <argp.h>
21 #include <assert.h>
22 #include <dirent.h>
23 #include <errno.h>
24 #include <error.h>
25 #include <fcntl.h>
26 #include <libintl.h>
27 #include <locale.h>
28 #include <paths.h>
29 #include <pthread.h>
30 #include <signal.h>
31 #include <stdbool.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <syslog.h>
36 #include <unistd.h>
37 #include <sys/mman.h>
38 #include <sys/socket.h>
39 #include <sys/stat.h>
40 #include <sys/uio.h>
41 #include <sys/un.h>
42
43 #include "dbg_log.h"
44 #include "nscd.h"
45 #include "selinux.h"
46 #include "../nss/nsswitch.h"
47 #include <device-nrs.h>
48 #ifdef HAVE_INOTIFY
49 # include <sys/inotify.h>
50 #endif
51
52 /* Get libc version number.  */
53 #include <version.h>
54
55 #define PACKAGE _libc_intl_domainname
56
57 /* Structure used by main() thread to keep track of the number of
58    active threads.  Used to limit how many threads it will create
59    and under a shutdown condition to wait till all in-progress
60    requests have finished before "turning off the lights".  */
61
62 typedef struct
63 {
64   int             num_active;
65   pthread_cond_t  thread_exit_cv;
66   pthread_mutex_t mutex;
67 } thread_info_t;
68
69 thread_info_t thread_info;
70
71 int do_shutdown;
72 int disabled_passwd;
73 int disabled_group;
74
75 typedef enum
76 {
77   /* Running in background as daemon.  */
78   RUN_DAEMONIZE,
79   /* Running in foreground but otherwise behave like a daemon,
80      i.e., detach from terminal and use syslog.  This allows
81      better integration with services like systemd.  */
82   RUN_FOREGROUND,
83   /* Run in foreground in debug mode.  */
84   RUN_DEBUG
85 } run_modes;
86
87 static run_modes run_mode = RUN_DAEMONIZE;
88
89 static const char *conffile = _PATH_NSCDCONF;
90
91 time_t start_time;
92
93 uintptr_t pagesize_m1;
94
95 int paranoia;
96 time_t restart_time;
97 time_t restart_interval = RESTART_INTERVAL;
98 const char *oldcwd;
99 uid_t old_uid;
100 gid_t old_gid;
101
102 static int check_pid (const char *file);
103 static int write_pid (const char *file);
104
105 /* Name and version of program.  */
106 static void print_version (FILE *stream, struct argp_state *state);
107 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
108
109 /* Function to print some extra text in the help message.  */
110 static char *more_help (int key, const char *text, void *input);
111
112 /* Definitions of arguments for argp functions.  */
113 static const struct argp_option options[] =
114 {
115   { "config-file", 'f', N_("NAME"), 0,
116     N_("Read configuration data from NAME") },
117   { "debug", 'd', NULL, 0,
118     N_("Do not fork and display messages on the current tty") },
119   { "foreground", 'F', NULL, 0,
120     N_("Do not fork, but otherwise behave like a daemon") },
121   { "nthreads", 't', N_("NUMBER"), 0, N_("Start NUMBER threads") },
122   { "shutdown", 'K', NULL, 0, N_("Shut the server down") },
123   { "statistics", 'g', NULL, 0, N_("Print current configuration statistics") },
124   { "invalidate", 'i', N_("TABLE"), 0,
125     N_("Invalidate the specified cache") },
126   { "secure", 'S', N_("TABLE,yes"), OPTION_HIDDEN,
127     N_("Use separate cache for each user")},
128   { NULL, 0, NULL, 0, NULL }
129 };
130
131 /* Short description of program.  */
132 static const char doc[] = N_("Name Service Cache Daemon.");
133
134 /* Prototype for option handler.  */
135 static error_t parse_opt (int key, char *arg, struct argp_state *state);
136
137 /* Data structure to communicate with argp functions.  */
138 static struct argp argp =
139 {
140   options, parse_opt, NULL, doc, NULL, more_help
141 };
142
143 /* True if only statistics are requested.  */
144 static bool get_stats;
145
146 int
147 main (int argc, char **argv)
148 {
149   int remaining;
150
151   /* Set locale via LC_ALL.  */
152   setlocale (LC_ALL, "");
153   /* Set the text message domain.  */
154   textdomain (PACKAGE);
155
156   /* Determine if the kernel has SELinux support.  */
157   nscd_selinux_enabled (&selinux_enabled);
158
159   /* Parse and process arguments.  */
160   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
161
162   if (remaining != argc)
163     {
164       error (0, 0, gettext ("wrong number of arguments"));
165       argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name);
166       exit (1);
167     }
168
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
172        server.  */
173     error (EXIT_FAILURE, 0,
174            _("failure while reading configuration file; this is fatal"));
175
176   /* Do we only get statistics?  */
177   if (get_stats)
178     /* Does not return.  */
179     receive_print_stats ();
180
181   /* Check if we are already running. */
182   if (check_pid (_PATH_NSCDPID))
183     error (EXIT_FAILURE, 0, _("already running"));
184
185   /* Remember when we started.  */
186   start_time = time (NULL);
187
188   /* Determine page size.  */
189   pagesize_m1 = getpagesize () - 1;
190
191   if (run_mode == RUN_DAEMONIZE || run_mode == RUN_FOREGROUND)
192     {
193       int i;
194       pid_t pid;
195
196       /* Behave like a daemon.  */
197       if (run_mode == RUN_DAEMONIZE)
198         {
199           pid = fork ();
200           if (pid == -1)
201             error (EXIT_FAILURE, errno, _("cannot fork"));
202           if (pid != 0)
203             exit (0);
204         }
205
206       int nullfd = open (_PATH_DEVNULL, O_RDWR);
207       if (nullfd != -1)
208         {
209           struct stat64 st;
210
211           if (fstat64 (nullfd, &st) == 0 && S_ISCHR (st.st_mode) != 0
212 #if defined DEV_NULL_MAJOR && defined DEV_NULL_MINOR
213               && st.st_rdev == makedev (DEV_NULL_MAJOR, DEV_NULL_MINOR)
214 #endif
215               )
216             {
217               /* It is the /dev/null special device alright.  */
218               (void) dup2 (nullfd, STDIN_FILENO);
219               (void) dup2 (nullfd, STDOUT_FILENO);
220               (void) dup2 (nullfd, STDERR_FILENO);
221
222               if (nullfd > 2)
223                 close (nullfd);
224             }
225           else
226             {
227               /* Ugh, somebody is trying to play a trick on us.  */
228               close (nullfd);
229               nullfd = -1;
230             }
231         }
232       int min_close_fd = nullfd == -1 ? 0 : STDERR_FILENO + 1;
233
234       DIR *d = opendir ("/proc/self/fd");
235       if (d != NULL)
236         {
237           struct dirent64 *dirent;
238           int dfdn = dirfd (d);
239
240           while ((dirent = readdir64 (d)) != NULL)
241             {
242               char *endp;
243               long int fdn = strtol (dirent->d_name, &endp, 10);
244
245               if (*endp == '\0' && fdn != dfdn && fdn >= min_close_fd)
246                 close ((int) fdn);
247             }
248
249           closedir (d);
250         }
251       else
252         for (i = min_close_fd; i < getdtablesize (); i++)
253           close (i);
254
255       setsid ();
256
257       if (chdir ("/") != 0)
258         error (EXIT_FAILURE, errno,
259                _("cannot change current working directory to \"/\""));
260
261       openlog ("nscd", LOG_CONS | LOG_ODELAY, LOG_DAEMON);
262
263       if (write_pid (_PATH_NSCDPID) < 0)
264         dbg_log ("%s: %s", _PATH_NSCDPID, strerror (errno));
265
266       if (!init_logfile ())
267         dbg_log (_("Could not create log file"));
268
269       /* Ignore job control signals.  */
270       signal (SIGTTOU, SIG_IGN);
271       signal (SIGTTIN, SIG_IGN);
272       signal (SIGTSTP, SIG_IGN);
273     }
274   else
275     /* In debug mode we are not paranoid.  */
276     paranoia = 0;
277
278   signal (SIGINT, termination_handler);
279   signal (SIGQUIT, termination_handler);
280   signal (SIGTERM, termination_handler);
281   signal (SIGPIPE, SIG_IGN);
282
283   /* Cleanup files created by a previous 'bind'.  */
284   unlink (_PATH_NSCDSOCKET);
285
286 #ifdef HAVE_INOTIFY
287   /* Use inotify to recognize changed files.  */
288   inotify_fd = inotify_init1 (IN_NONBLOCK);
289 # ifndef __ASSUME_IN_NONBLOCK
290   if (inotify_fd == -1 && errno == ENOSYS)
291     {
292       inotify_fd = inotify_init ();
293       if (inotify_fd != -1)
294         fcntl (inotify_fd, F_SETFL, O_RDONLY | O_NONBLOCK);
295     }
296 # endif
297 #endif
298
299 #ifdef USE_NSCD
300   /* Make sure we do not get recursive calls.  */
301   __nss_disable_nscd (register_traced_file);
302 #endif
303
304   /* Init databases.  */
305   nscd_init ();
306
307   /* Start the SELinux AVC.  */
308   if (selinux_enabled)
309     nscd_avc_init ();
310
311   /* Handle incoming requests */
312   start_threads ();
313
314   return 0;
315 }
316
317
318 /* Handle program arguments.  */
319 static error_t
320 parse_opt (int key, char *arg, struct argp_state *state)
321 {
322   switch (key)
323     {
324     case 'd':
325       ++debug_level;
326       run_mode = RUN_DEBUG;
327       break;
328
329     case 'F':
330       run_mode = RUN_FOREGROUND;
331       break;
332
333     case 'f':
334       conffile = arg;
335       break;
336
337     case 'K':
338       if (getuid () != 0)
339         error (4, 0, _("Only root is allowed to use this option!"));
340       {
341         int sock = nscd_open_socket ();
342
343         if (sock == -1)
344           exit (EXIT_FAILURE);
345
346         request_header req;
347         req.version = NSCD_VERSION;
348         req.type = SHUTDOWN;
349         req.key_len = 0;
350
351         ssize_t nbytes = TEMP_FAILURE_RETRY (send (sock, &req,
352                                                    sizeof (request_header),
353                                                    MSG_NOSIGNAL));
354         close (sock);
355         exit (nbytes != sizeof (request_header) ? EXIT_FAILURE : EXIT_SUCCESS);
356       }
357
358     case 'g':
359       get_stats = true;
360       break;
361
362     case 'i':
363       if (getuid () != 0)
364         error (4, 0, _("Only root is allowed to use this option!"));
365       else
366         {
367           int sock = nscd_open_socket ();
368
369           if (sock == -1)
370             exit (EXIT_FAILURE);
371
372           dbtype cnt;
373           for (cnt = pwddb; cnt < lastdb; ++cnt)
374             if (strcmp (arg, dbnames[cnt]) == 0)
375               break;
376
377           if (cnt == lastdb)
378             {
379               argp_error (state, _("'%s' is not a known database"), arg);
380               return EINVAL;
381             }
382
383           size_t arg_len = strlen (arg) + 1;
384           struct
385           {
386             request_header req;
387             char arg[arg_len];
388           } reqdata;
389
390           reqdata.req.key_len = strlen (arg) + 1;
391           reqdata.req.version = NSCD_VERSION;
392           reqdata.req.type = INVALIDATE;
393           memcpy (reqdata.arg, arg, arg_len);
394
395           ssize_t nbytes = TEMP_FAILURE_RETRY (send (sock, &reqdata,
396                                                      sizeof (request_header)
397                                                      + arg_len,
398                                                      MSG_NOSIGNAL));
399
400           if (nbytes != sizeof (request_header) + arg_len)
401             {
402               int err = errno;
403               close (sock);
404               error (EXIT_FAILURE, err, _("write incomplete"));
405             }
406
407           /* Wait for ack.  Older nscd just closed the socket when
408              prune_cache finished, silently ignore that.  */
409           int32_t resp = 0;
410           nbytes = TEMP_FAILURE_RETRY (read (sock, &resp, sizeof (resp)));
411           if (nbytes != 0 && nbytes != sizeof (resp))
412             {
413               int err = errno;
414               close (sock);
415               error (EXIT_FAILURE, err, _("cannot read invalidate ACK"));
416             }
417
418           close (sock);
419
420           if (resp != 0)
421             error (EXIT_FAILURE, resp, _("invalidation failed"));
422
423           exit (0);
424         }
425
426     case 't':
427       nthreads = atol (arg);
428       break;
429
430     case 'S':
431       error (0, 0, _("secure services not implemented anymore"));
432       break;
433
434     default:
435       return ARGP_ERR_UNKNOWN;
436     }
437
438   return 0;
439 }
440
441 /* Print bug-reporting information in the help message.  */
442 static char *
443 more_help (int key, const char *text, void *input)
444 {
445   char *tables, *tp = NULL;
446
447   switch (key)
448     {
449     case ARGP_KEY_HELP_EXTRA:
450       {
451         dbtype cnt;
452
453         tables = xmalloc (sizeof (dbnames) + 1);
454         for (cnt = 0; cnt < lastdb; cnt++)
455           {
456             strcat (tables, dbnames[cnt]);
457             strcat (tables, " ");
458           }
459       }
460
461       /* We print some extra information.  */
462       if (asprintf (&tp, gettext ("\
463 Supported tables:\n\
464 %s\n\
465 \n\
466 For bug reporting instructions, please see:\n\
467 %s.\n\
468 "), tables, REPORT_BUGS_TO) < 0)
469         tp = NULL;
470       free (tables);
471       return tp;
472
473     default:
474       break;
475     }
476
477   return (char *) text;
478 }
479
480 /* Print the version information.  */
481 static void
482 print_version (FILE *stream, struct argp_state *state)
483 {
484   fprintf (stream, "nscd %s%s\n", PKGVERSION, VERSION);
485   fprintf (stream, gettext ("\
486 Copyright (C) %s Free Software Foundation, Inc.\n\
487 This is free software; see the source for copying conditions.  There is NO\n\
488 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
489 "), "2014");
490   fprintf (stream, gettext ("Written by %s.\n"),
491            "Thorsten Kukuk and Ulrich Drepper");
492 }
493
494
495 /* Create a socket connected to a name.  */
496 int
497 nscd_open_socket (void)
498 {
499   struct sockaddr_un addr;
500   int sock;
501
502   sock = socket (PF_UNIX, SOCK_STREAM, 0);
503   if (sock < 0)
504     return -1;
505
506   addr.sun_family = AF_UNIX;
507   assert (sizeof (addr.sun_path) >= sizeof (_PATH_NSCDSOCKET));
508   strcpy (addr.sun_path, _PATH_NSCDSOCKET);
509   if (connect (sock, (struct sockaddr *) &addr, sizeof (addr)) < 0)
510     {
511       close (sock);
512       return -1;
513     }
514
515   return sock;
516 }
517
518
519 /* Cleanup.  */
520 void
521 termination_handler (int signum)
522 {
523   close_sockets ();
524
525   /* Clean up the file created by 'bind'.  */
526   unlink (_PATH_NSCDSOCKET);
527
528   /* Clean up pid file.  */
529   unlink (_PATH_NSCDPID);
530
531   // XXX Terminate threads.
532
533   /* Synchronize memory.  */
534   for (int cnt = 0; cnt < lastdb; ++cnt)
535     {
536       if (!dbs[cnt].enabled || dbs[cnt].head == NULL)
537         continue;
538
539       /* Make sure nobody keeps using the database.  */
540       dbs[cnt].head->timestamp = 0;
541
542       if (dbs[cnt].persistent)
543         // XXX async OK?
544         msync (dbs[cnt].head, dbs[cnt].memsize, MS_ASYNC);
545     }
546
547   _exit (EXIT_SUCCESS);
548 }
549
550 /* Returns 1 if the process in pid file FILE is running, 0 if not.  */
551 static int
552 check_pid (const char *file)
553 {
554   FILE *fp;
555
556   fp = fopen (file, "r");
557   if (fp)
558     {
559       pid_t pid;
560       int n;
561
562       n = fscanf (fp, "%d", &pid);
563       fclose (fp);
564
565       /* If we cannot parse the file default to assuming nscd runs.
566          If the PID is alive, assume it is running.  That all unless
567          the PID is the same as the current process' since tha latter
568          can mean we re-exec.  */
569       if ((n != 1 || kill (pid, 0) == 0) && pid != getpid ())
570         return 1;
571     }
572
573   return 0;
574 }
575
576 /* Write the current process id to the file FILE.
577    Returns 0 if successful, -1 if not.  */
578 static int
579 write_pid (const char *file)
580 {
581   FILE *fp;
582
583   fp = fopen (file, "w");
584   if (fp == NULL)
585     return -1;
586
587   fprintf (fp, "%d\n", getpid ());
588
589   int result = fflush (fp) || ferror (fp) ? -1 : 0;
590
591   fclose (fp);
592
593   return result;
594 }