Blame SOURCES/glibc-rh1048123.patch

147e83
commit 0582f6b3d6fab2128ee43a06250571922ee7c1e3
147e83
Author: Andreas Schwab <schwab@suse.de>
147e83
Date:   Sun Dec 23 09:45:07 2012 +0100
147e83
147e83
    nscd: don't fork twice
147e83
147e83
commit 532a60357ef4c5852cc1bf836cfd9d6f093ef204
147e83
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
147e83
Date:   Mon Mar 3 22:51:39 2014 +0530
147e83
147e83
    nscd: Improved support for tracking startup failure in nscd service (BZ #16639)
147e83
    
147e83
    Currently, the nscd parent process parses commandline options and
147e83
    configuration, forks on startup and immediately exits with a success.
147e83
    If the child process encounters some error after this, it goes
147e83
    undetected and any services started up after it may have to repeatedly
147e83
    check to make sure that the nscd service did actually start up and is
147e83
    serving requests.
147e83
    
147e83
    To make this process more reliable, I have added a pipe between the
147e83
    parent and child process, through which the child process sends a
147e83
    notification to the parent informing it of its status.  The parent
147e83
    waits for this status and once it receives it, exits with the
147e83
    corresponding exit code.  So if the child service sends a success
147e83
    status (0), the parent exits with a success status.  Similarly for
147e83
    error conditions, the child sends the non-zero status code, which the
147e83
    parent passes on as the exit code.
147e83
    
147e83
    This, along with setting the nscd service type to forking in its
147e83
    systemd configuration file, allows systemd to be certain that the nscd
147e83
    service is ready and is accepting connections.
147e83
147e83
147e83
diff --git glibc-2.17-c758a686/nscd/connections.c glibc-2.17-c758a686/nscd/connections.c
147e83
index f463f45..180ae77 100644
147e83
--- glibc-2.17-c758a686/nscd/connections.c
147e83
+++ glibc-2.17-c758a686/nscd/connections.c
147e83
@@ -649,8 +649,8 @@ cannot create read-only descriptor for \"%s\"; no mmap"),
147e83
 		  close (fd);
147e83
 	      }
147e83
 	    else if (errno == EACCES)
147e83
-	      error (EXIT_FAILURE, 0, _("cannot access '%s'"),
147e83
-		     dbs[cnt].db_filename);
147e83
+	      do_exit (EXIT_FAILURE, 0, _("cannot access '%s'"),
147e83
+		       dbs[cnt].db_filename);
147e83
 	  }
147e83
 
147e83
 	if (dbs[cnt].head == NULL)
147e83
@@ -699,8 +699,7 @@ cannot create read-only descriptor for \"%s\"; no mmap"),
147e83
 		  {
147e83
 		    dbg_log (_("database for %s corrupted or simultaneously used; remove %s manually if necessary and restart"),
147e83
 			     dbnames[cnt], dbs[cnt].db_filename);
147e83
-		    // XXX Correct way to terminate?
147e83
-		    exit (1);
147e83
+		    do_exit (1, 0, NULL);
147e83
 		  }
147e83
 
147e83
 		if  (dbs[cnt].persistent)
147e83
@@ -867,7 +866,7 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
147e83
   if (sock < 0)
147e83
     {
147e83
       dbg_log (_("cannot open socket: %s"), strerror (errno));
147e83
-      exit (errno == EACCES ? 4 : 1);
147e83
+      do_exit (errno == EACCES ? 4 : 1, 0, NULL);
147e83
     }
147e83
   /* Bind a name to the socket.  */
147e83
   struct sockaddr_un sock_addr;
147e83
@@ -876,7 +875,7 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
147e83
   if (bind (sock, (struct sockaddr *) &sock_addr, sizeof (sock_addr)) < 0)
147e83
     {
147e83
       dbg_log ("%s: %s", _PATH_NSCDSOCKET, strerror (errno));
147e83
-      exit (errno == EACCES ? 4 : 1);
147e83
+      do_exit (errno == EACCES ? 4 : 1, 0, NULL);
147e83
     }
147e83
 
147e83
 #ifndef __ASSUME_SOCK_CLOEXEC
147e83
@@ -888,7 +887,7 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
147e83
 	{
147e83
 	  dbg_log (_("cannot change socket to nonblocking mode: %s"),
147e83
 		   strerror (errno));
147e83
-	  exit (1);
147e83
+	  do_exit (1, 0, NULL);
147e83
 	}
147e83
 
147e83
       /* The descriptor needs to be closed on exec.  */
147e83
@@ -896,7 +895,7 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
147e83
 	{
147e83
 	  dbg_log (_("cannot set socket to close on exec: %s"),
147e83
 		   strerror (errno));
147e83
-	  exit (1);
147e83
+	  do_exit (1, 0, NULL);
147e83
 	}
147e83
     }
147e83
 #endif
147e83
@@ -909,7 +908,7 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
147e83
     {
147e83
       dbg_log (_("cannot enable socket to accept connections: %s"),
147e83
 	       strerror (errno));
147e83
-      exit (1);
147e83
+      do_exit (1, 0, NULL);
147e83
     }
147e83
 
147e83
 #ifdef HAVE_NETLINK
147e83
@@ -953,7 +952,7 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
147e83
 		      dbg_log (_("\
147e83
 cannot change socket to nonblocking mode: %s"),
147e83
 			       strerror (errno));
147e83
-		      exit (1);
147e83
+		      do_exit (1, 0, NULL);
147e83
 		    }
147e83
 
147e83
 		  /* The descriptor needs to be closed on exec.  */
147e83
@@ -962,7 +961,7 @@ cannot change socket to nonblocking mode: %s"),
147e83
 		    {
147e83
 		      dbg_log (_("cannot set socket to close on exec: %s"),
147e83
 			       strerror (errno));
147e83
-		      exit (1);
147e83
+		      do_exit (1, 0, NULL);
147e83
 		    }
147e83
 		}
147e83
 # endif
147e83
@@ -2392,7 +2391,7 @@ start_threads (void)
147e83
       if (pthread_cond_init (&dbs[i].prune_cond, &condattr) != 0)
147e83
 	{
147e83
 	  dbg_log (_("could not initialize conditional variable"));
147e83
-	  exit (1);
147e83
+	  do_exit (1, 0, NULL);
147e83
 	}
147e83
 
147e83
       pthread_t th;
147e83
@@ -2400,7 +2399,7 @@ start_threads (void)
147e83
 	  && pthread_create (&th, &attr, nscd_run_prune, (void *) i) != 0)
147e83
 	{
147e83
 	  dbg_log (_("could not start clean-up thread; terminating"));
147e83
-	  exit (1);
147e83
+	  do_exit (1, 0, NULL);
147e83
 	}
147e83
     }
147e83
 
147e83
@@ -2414,13 +2413,17 @@ start_threads (void)
147e83
 	  if (i == 0)
147e83
 	    {
147e83
 	      dbg_log (_("could not start any worker thread; terminating"));
147e83
-	      exit (1);
147e83
+	      do_exit (1, 0, NULL);
147e83
 	    }
147e83
 
147e83
 	  break;
147e83
 	}
147e83
     }
147e83
 
147e83
+  /* Now it is safe to let the parent know that we're doing fine and it can
147e83
+     exit.  */
147e83
+  notify_parent (0);
147e83
+
147e83
   /* Determine how much room for descriptors we should initially
147e83
      allocate.  This might need to change later if we cap the number
147e83
      with MAXCONN.  */
147e83
@@ -2465,8 +2468,8 @@ begin_drop_privileges (void)
147e83
   if (pwd == NULL)
147e83
     {
147e83
       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
147e83
-      error (EXIT_FAILURE, 0, _("Failed to run nscd as user '%s'"),
147e83
-	     server_user);
147e83
+      do_exit (EXIT_FAILURE, 0,
147e83
+	       _("Failed to run nscd as user '%s'"), server_user);
147e83
     }
147e83
 
147e83
   server_uid = pwd->pw_uid;
147e83
@@ -2483,7 +2486,8 @@ begin_drop_privileges (void)
147e83
     {
147e83
       /* This really must never happen.  */
147e83
       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
147e83
-      error (EXIT_FAILURE, errno, _("initial getgrouplist failed"));
147e83
+      do_exit (EXIT_FAILURE, errno,
147e83
+	       _("initial getgrouplist failed"));
147e83
     }
147e83
 
147e83
   server_groups = (gid_t *) xmalloc (server_ngroups * sizeof (gid_t));
147e83
@@ -2492,7 +2496,7 @@ begin_drop_privileges (void)
147e83
       == -1)
147e83
     {
147e83
       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
147e83
-      error (EXIT_FAILURE, errno, _("getgrouplist failed"));
147e83
+      do_exit (EXIT_FAILURE, errno, _("getgrouplist failed"));
147e83
     }
147e83
 }
147e83
 
147e83
@@ -2510,7 +2514,7 @@ finish_drop_privileges (void)
147e83
   if (setgroups (server_ngroups, server_groups) == -1)
147e83
     {
147e83
       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
147e83
-      error (EXIT_FAILURE, errno, _("setgroups failed"));
147e83
+      do_exit (EXIT_FAILURE, errno, _("setgroups failed"));
147e83
     }
147e83
 
147e83
   int res;
147e83
@@ -2521,8 +2525,7 @@ finish_drop_privileges (void)
147e83
   if (res == -1)
147e83
     {
147e83
       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
147e83
-      perror ("setgid");
147e83
-      exit (4);
147e83
+      do_exit (4, errno, "setgid");
147e83
     }
147e83
 
147e83
   if (paranoia)
147e83
@@ -2532,8 +2535,7 @@ finish_drop_privileges (void)
147e83
   if (res == -1)
147e83
     {
147e83
       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
147e83
-      perror ("setuid");
147e83
-      exit (4);
147e83
+      do_exit (4, errno, "setuid");
147e83
     }
147e83
 
147e83
 #if defined HAVE_LIBAUDIT && defined HAVE_LIBCAP
147e83
diff --git glibc-2.17-c758a686/nscd/nscd.c glibc-2.17-c758a686/nscd/nscd.c
147e83
index 63d9d83..5680378 100644
147e83
--- glibc-2.17-c758a686/nscd/nscd.c
147e83
+++ glibc-2.17-c758a686/nscd/nscd.c
147e83
@@ -39,6 +39,8 @@
147e83
 #include <sys/stat.h>
147e83
 #include <sys/uio.h>
147e83
 #include <sys/un.h>
147e83
+#include <sys/wait.h>
147e83
+#include <stdarg.h>
147e83
 
147e83
 #include "dbg_log.h"
147e83
 #include "nscd.h"
147e83
@@ -101,6 +103,7 @@ gid_t old_gid;
147e83
 
147e83
 static int check_pid (const char *file);
147e83
 static int write_pid (const char *file);
147e83
+static int monitor_child (int fd);
147e83
 
147e83
 /* Name and version of program.  */
147e83
 static void print_version (FILE *stream, struct argp_state *state);
147e83
@@ -142,6 +145,7 @@ static struct argp argp =
147e83
 
147e83
 /* True if only statistics are requested.  */
147e83
 static bool get_stats;
147e83
+static int parent_fd = -1;
147e83
 
147e83
 int
147e83
 main (int argc, char **argv)
147e83
@@ -196,11 +200,27 @@ main (int argc, char **argv)
147e83
       /* Behave like a daemon.  */
147e83
       if (run_mode == RUN_DAEMONIZE)
147e83
 	{
147e83
+	  int fd[2];
147e83
+
147e83
+	  if (pipe (fd) != 0)
147e83
+	    error (EXIT_FAILURE, errno,
147e83
+		   _("cannot create a pipe to talk to the child"));
147e83
+
147e83
 	  pid = fork ();
147e83
 	  if (pid == -1)
147e83
 	    error (EXIT_FAILURE, errno, _("cannot fork"));
147e83
 	  if (pid != 0)
147e83
-	    exit (0);
147e83
+	    {
147e83
+	      /* The parent only reads from the child.  */
147e83
+	      close (fd[1]);
147e83
+	      exit (monitor_child (fd[0]));
147e83
+	    }
147e83
+	  else
147e83
+	    {
147e83
+	      /* The child only writes to the parent.  */
147e83
+	      close (fd[0]);
147e83
+	      parent_fd = fd[1];
147e83
+	    }
147e83
 	}
147e83
 
147e83
       int nullfd = open (_PATH_DEVNULL, O_RDWR);
147e83
@@ -242,7 +262,8 @@ main (int argc, char **argv)
147e83
 	      char *endp;
147e83
 	      long int fdn = strtol (dirent->d_name, &endp, 10);
147e83
 
147e83
-	      if (*endp == '\0' && fdn != dfdn && fdn >= min_close_fd)
147e83
+	      if (*endp == '\0' && fdn != dfdn && fdn >= min_close_fd
147e83
+		  && fdn != parent_fd)
147e83
 		close ((int) fdn);
147e83
 	    }
147e83
 
147e83
@@ -250,22 +271,14 @@ main (int argc, char **argv)
147e83
 	}
147e83
       else
147e83
 	for (i = min_close_fd; i < getdtablesize (); i++)
147e83
-	  close (i);
147e83
+	  if (i != parent_fd)
147e83
+	    close (i);
147e83
 
147e83
-      if (run_mode == RUN_DAEMONIZE)
147e83
-	{
147e83
-	  pid = fork ();
147e83
-	  if (pid == -1)
147e83
-	    error (EXIT_FAILURE, errno, _("cannot fork"));
147e83
-	  if (pid != 0)
147e83
-	    exit (0);
147e83
-	}
147e83
-
147e83
       setsid ();
147e83
 
147e83
       if (chdir ("/") != 0)
147e83
-	error (EXIT_FAILURE, errno,
147e83
-	       _("cannot change current working directory to \"/\""));
147e83
+	do_exit (EXIT_FAILURE, errno,
147e83
+		 _("cannot change current working directory to \"/\""));
147e83
 
147e83
       openlog ("nscd", LOG_CONS | LOG_ODELAY, LOG_DAEMON);
147e83
 
147e83
@@ -592,3 +614,79 @@ write_pid (const char *file)
147e83
 
147e83
   return result;
147e83
 }
147e83
+
147e83
+static int
147e83
+monitor_child (int fd)
147e83
+{
147e83
+  int child_ret = 0;
147e83
+  int ret = read (fd, &child_ret, sizeof (child_ret));
147e83
+
147e83
+  /* The child terminated with an error, either via exit or some other abnormal
147e83
+     method, like a segfault.  */
147e83
+  if (ret <= 0 || child_ret != 0)
147e83
+    {
147e83
+      int err = wait (&child_ret);
147e83
+
147e83
+      if (err < 0)
147e83
+	{
147e83
+	  fprintf (stderr, _("wait failed"));
147e83
+	  return 1;
147e83
+	}
147e83
+
147e83
+      fprintf (stderr, _("child exited with status %d"),
147e83
+	       WEXITSTATUS (child_ret));
147e83
+      if (WIFSIGNALED (child_ret))
147e83
+	fprintf (stderr, _(", terminated by signal %d.\n"),
147e83
+		 WTERMSIG (child_ret));
147e83
+      else
147e83
+	fprintf (stderr, ".\n");
147e83
+    }
147e83
+
147e83
+  /* We have the child status, so exit with that code.  */
147e83
+  close (fd);
147e83
+
147e83
+  return child_ret;
147e83
+}
147e83
+
147e83
+void
147e83
+do_exit (int child_ret, int errnum, const char *format, ...)
147e83
+{
147e83
+  if (parent_fd != -1)
147e83
+    {
147e83
+      int ret = write (parent_fd, &child_ret, sizeof (child_ret));
147e83
+      assert (ret == sizeof (child_ret));
147e83
+      close (parent_fd);
147e83
+    }
147e83
+
147e83
+  if (format != NULL)
147e83
+    {
147e83
+      /* Emulate error() since we don't have a va_list variant for it.  */
147e83
+      va_list argp;
147e83
+
147e83
+      fflush (stdout);
147e83
+
147e83
+      fprintf (stderr, "%s: ", program_invocation_name);
147e83
+
147e83
+      va_start (argp, format);
147e83
+      vfprintf (stderr, format, argp);
147e83
+      va_end (argp);
147e83
+
147e83
+      fprintf (stderr, ": %s\n", strerror (errnum));
147e83
+      fflush (stderr);
147e83
+    }
147e83
+
147e83
+  /* Finally, exit.  */
147e83
+  exit (child_ret);
147e83
+}
147e83
+
147e83
+void
147e83
+notify_parent (int child_ret)
147e83
+{
147e83
+  if (parent_fd == -1)
147e83
+    return;
147e83
+
147e83
+  int ret = write (parent_fd, &child_ret, sizeof (child_ret));
147e83
+  assert (ret == sizeof (child_ret));
147e83
+  close (parent_fd);
147e83
+  parent_fd = -1;
147e83
+}
147e83
diff --git glibc-2.17-c758a686/nscd/nscd.h glibc-2.17-c758a686/nscd/nscd.h
147e83
index 972f462..529b3f5 100644
147e83
--- glibc-2.17-c758a686/nscd/nscd.h
147e83
+++ glibc-2.17-c758a686/nscd/nscd.h
147e83
@@ -205,6 +205,8 @@ extern gid_t old_gid;
147e83
 /* nscd.c */
147e83
 extern void termination_handler (int signum) __attribute__ ((__noreturn__));
147e83
 extern int nscd_open_socket (void);
147e83
+void notify_parent (int child_ret);
147e83
+void do_exit (int child_ret, int errnum, const char *format, ...);
147e83
 
147e83
 /* connections.c */
147e83
 extern void nscd_init (void);
147e83
diff --git glibc-2.17-c758a686/nscd/selinux.c glibc-2.17-c758a686/nscd/selinux.c
147e83
index e477254..46b0ea9 100644
147e83
--- glibc-2.17-c758a686/nscd/selinux.c
147e83
+++ glibc-2.17-c758a686/nscd/selinux.c
147e83
@@ -179,7 +179,7 @@ preserve_capabilities (void)
147e83
   if (prctl (PR_SET_KEEPCAPS, 1) == -1)
147e83
     {
147e83
       dbg_log (_("Failed to set keep-capabilities"));
147e83
-      error (EXIT_FAILURE, errno, _("prctl(KEEPCAPS) failed"));
147e83
+      do_exit (EXIT_FAILURE, errno, _("prctl(KEEPCAPS) failed"));
147e83
       /* NOTREACHED */
147e83
     }
147e83
 
147e83
@@ -194,7 +194,7 @@ preserve_capabilities (void)
147e83
 	cap_free (tmp_caps);
147e83
 
147e83
       dbg_log (_("Failed to initialize drop of capabilities"));
147e83
-      error (EXIT_FAILURE, 0, _("cap_init failed"));
147e83
+      do_exit (EXIT_FAILURE, 0, _("cap_init failed"));
147e83
     }
147e83
 
147e83
   /* There is no reason why these should not work.  */
147e83
@@ -216,7 +216,7 @@ preserve_capabilities (void)
147e83
     {
147e83
       cap_free (new_caps);
147e83
       dbg_log (_("Failed to drop capabilities"));
147e83
-      error (EXIT_FAILURE, 0, _("cap_set_proc failed"));
147e83
+      do_exit (EXIT_FAILURE, 0, _("cap_set_proc failed"));
147e83
     }
147e83
 
147e83
   return new_caps;
147e83
@@ -233,7 +233,7 @@ install_real_capabilities (cap_t new_caps)
147e83
     {
147e83
       cap_free (new_caps);
147e83
       dbg_log (_("Failed to drop capabilities"));
147e83
-      error (EXIT_FAILURE, 0, _("cap_set_proc failed"));
147e83
+      do_exit (EXIT_FAILURE, 0, _("cap_set_proc failed"));
147e83
       /* NOTREACHED */
147e83
     }
147e83
 
147e83
@@ -242,7 +242,7 @@ install_real_capabilities (cap_t new_caps)
147e83
   if (prctl (PR_SET_KEEPCAPS, 0) == -1)
147e83
     {
147e83
       dbg_log (_("Failed to unset keep-capabilities"));
147e83
-      error (EXIT_FAILURE, errno, _("prctl(KEEPCAPS) failed"));
147e83
+      do_exit (EXIT_FAILURE, errno, _("prctl(KEEPCAPS) failed"));
147e83
       /* NOTREACHED */
147e83
     }
147e83
 }
147e83
@@ -258,7 +258,7 @@ nscd_selinux_enabled (int *selinux_enabled)
147e83
   if (*selinux_enabled < 0)
147e83
     {
147e83
       dbg_log (_("Failed to determine if kernel supports SELinux"));
147e83
-      exit (EXIT_FAILURE);
147e83
+      do_exit (EXIT_FAILURE, 0, NULL);
147e83
     }
147e83
 }
147e83
 
147e83
@@ -272,7 +272,7 @@ avc_create_thread (void (*run) (void))
147e83
   rc =
147e83
     pthread_create (&avc_notify_thread, NULL, (void *(*) (void *)) run, NULL);
147e83
   if (rc != 0)
147e83
-    error (EXIT_FAILURE, rc, _("Failed to start AVC thread"));
147e83
+    do_exit (EXIT_FAILURE, rc, _("Failed to start AVC thread"));
147e83
 
147e83
   return &avc_notify_thread;
147e83
 }
147e83
@@ -294,7 +294,7 @@ avc_alloc_lock (void)
147e83
 
147e83
   avc_mutex = malloc (sizeof (pthread_mutex_t));
147e83
   if (avc_mutex == NULL)
147e83
-    error (EXIT_FAILURE, errno, _("Failed to create AVC lock"));
147e83
+    do_exit (EXIT_FAILURE, errno, _("Failed to create AVC lock"));
147e83
   pthread_mutex_init (avc_mutex, NULL);
147e83
 
147e83
   return avc_mutex;
147e83
@@ -334,7 +334,7 @@ nscd_avc_init (void)
147e83
   avc_entry_ref_init (&aeref);
147e83
 
147e83
   if (avc_init ("avc", NULL, &log_cb, &thread_cb, &lock_cb) < 0)
147e83
-    error (EXIT_FAILURE, errno, _("Failed to start AVC"));
147e83
+    do_exit (EXIT_FAILURE, errno, _("Failed to start AVC"));
147e83
   else
147e83
     dbg_log (_("Access Vector Cache (AVC) started"));
147e83
 #ifdef HAVE_LIBAUDIT
147e83
--- glibc-2.17-c758a686/releng/nscd.service	2012-11-06 03:03:19.000000000 +0530
147e83
+++ glibc-2.17-c758a686/releng/nscd.service	2014-02-28 16:59:51.096630222 +0530
147e83
@@ -1,10 +1,13 @@
147e83
+# systemd service file for nscd
147e83
+
147e83
 [Unit]
147e83
 Description=Name Service Cache Daemon
147e83
 After=syslog.target
147e83
 
147e83
 [Service]
147e83
+Type=forking
147e83
 EnvironmentFile=-/etc/sysconfig/nscd
147e83
-ExecStart=/usr/sbin/nscd --foreground $NSCD_OPTIONS
147e83
+ExecStart=/usr/sbin/nscd $NSCD_OPTIONS
147e83
 ExecStop=/usr/sbin/nscd --shutdown
147e83
 ExecReload=/usr/sbin/nscd -i passwd
147e83
 ExecReload=/usr/sbin/nscd -i group
147e83
@@ -12,6 +14,7 @@
147e83
 ExecReload=/usr/sbin/nscd -i services
147e83
 ExecReload=/usr/sbin/nscd -i netgroup
147e83
 Restart=always
147e83
+PIDFile=/run/nscd/nscd.pid
147e83
 
147e83
 [Install]
147e83
 WantedBy=multi-user.target