about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--nscd/connections.c105
-rw-r--r--nscd/nscd.c41
-rw-r--r--sysdeps/mips/dl-machine.h4
4 files changed, 119 insertions, 44 deletions
diff --git a/ChangeLog b/ChangeLog
index afac75cd84..8714e624c9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2002-01-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* nscd/nscd.c (drop_privileges): Removed.  Adjust caller.
+	* nscd/connections.c (begin_drop_privileges): New function.
+	(finish_drop_privileges): New function.
+	(nscd_init): Call the new functions which also install all groups
+	for the server user.
+
+2002-01-17  H.J. Lu  <hjl@gnu.org>
+
+	* sysdeps/mips/dl-machine.h (__dl_runtime_resolve): Remove
+	`const' from `got'.
+
 2002-01-17  Martin Schwidefsky  <schwidefsky@de.ibm.com>
 
 	* sysdeps/unix/sysv/linux/s390/s390-64/getcontext.S: Use 64 bit
diff --git a/nscd/connections.c b/nscd/connections.c
index 7f7514f8f6..7414ef60a3 100644
--- a/nscd/connections.c
+++ b/nscd/connections.c
@@ -1,5 +1,5 @@
 /* Inner loops of cache daemon.
-   Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -21,7 +21,10 @@
 #include <assert.h>
 #include <error.h>
 #include <errno.h>
+#include <grp.h>
 #include <pthread.h>
+#include <pwd.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <libintl.h>
@@ -35,6 +38,24 @@
 #include "nscd.h"
 #include "dbg_log.h"
 
+/* Wrapper functions with error checking for standard functions.  */
+extern void *xmalloc (size_t n);
+extern void *xcalloc (size_t n, size_t s);
+extern void *xrealloc (void *o, size_t n);
+
+/* Support to run nscd as an unprivileged user */
+const char *server_user;
+static uid_t server_uid;
+static gid_t server_gid;
+static gid_t *server_groups;
+#ifndef NGROUPS
+# define NGROUPS 32
+#endif
+static int server_ngroups = NGROUPS;
+
+static void begin_drop_privileges (void);
+static void finish_drop_privileges (void);
+
 
 /* Mapping of request type to database.  */
 static const dbtype serv2db[LASTDBREQ + 1] =
@@ -125,6 +146,19 @@ nscd_init (const char *conffile)
       dbg_log (_("cannot read configuration file; this is fatal"));
       exit (1);
     }
+
+  /* Secure mode and unprivileged mode are incompatible */
+  if (server_user != NULL && secure_in_use)
+    {
+      dbg_log (_("Cannot run nscd in secure mode as unprivileged user"));
+      exit (1);
+    }
+
+  /* Look up unprivileged uid/gid/groups before we start listening on the
+     socket  */
+  if (server_user != NULL)
+    begin_drop_privileges ();
+
   if (nthreads == -1)
     /* No configuration for this value, assume a default.  */
     nthreads = 2 * lastdb;
@@ -184,6 +218,10 @@ nscd_init (const char *conffile)
 	       strerror (errno));
       exit (1);
     }
+
+  /* Change to unprivileged uid/gid/groups if specifed in config file */
+  if (server_user != NULL)
+    finish_drop_privileges ();
 }
 
 
@@ -535,3 +573,68 @@ start_threads (void)
 
   nscd_run ((void *) 0);
 }
+
+
+/* Look up the uid, gid, and supplementary groups to run nscd as. When
+   this function is called, we are not listening on the nscd socket yet so
+   we can just use the ordinary lookup functions without causing a lockup  */
+static void
+begin_drop_privileges (void)
+{
+  struct passwd *pwd;
+
+  pwd = getpwnam (server_user);
+
+  if (pwd == NULL)
+    {
+      dbg_log (_("Failed to run nscd as user '%s'"), server_user);
+      error (EXIT_FAILURE, 0, _("Failed to run nscd as user '%s'"),
+	     server_user);
+    }
+
+  server_uid = pwd->pw_uid;
+  server_gid = pwd->pw_gid;
+
+  server_groups = (gid_t *) xmalloc (server_ngroups * sizeof (gid_t));
+
+  if (getgrouplist (server_user, server_gid, server_groups, &server_ngroups)
+      == 0)
+    return;
+
+  server_groups = (gid_t *) xrealloc (server_groups,
+				      server_ngroups * sizeof (gid_t));
+
+  if (getgrouplist (server_user, server_gid, server_groups, &server_ngroups)
+      == -1)
+    {
+      dbg_log (_("Failed to run nscd as user '%s'"), server_user);
+      error (EXIT_FAILURE, errno, _("getgrouplist failed"));
+    }
+}
+
+
+/* Call setgroups(), setgid(), and setuid() to drop root privileges and
+   run nscd as the user specified in the configuration file.  */
+static void
+finish_drop_privileges (void)
+{
+  if (setgroups (server_ngroups, server_groups) == -1)
+    {
+      dbg_log (_("Failed to run nscd as user '%s'"), server_user);
+      error (EXIT_FAILURE, errno, _("setgroups failed"));
+    }
+
+  if (setgid (server_gid) == -1)
+    {
+      dbg_log (_("Failed to run nscd as user '%s'"), server_user);
+      perror ("setgid");
+      exit (1);
+    }
+
+  if (setuid (server_uid) == -1)
+    {
+      dbg_log (_("Failed to run nscd as user '%s'"), server_user);
+      perror ("setuid");
+      exit (1);
+    }
+}
diff --git a/nscd/nscd.c b/nscd/nscd.c
index 52385a1730..045256b07f 100644
--- a/nscd/nscd.c
+++ b/nscd/nscd.c
@@ -23,11 +23,9 @@
 #include <assert.h>
 #include <errno.h>
 #include <error.h>
-#include <grp.h>
 #include <libintl.h>
 #include <locale.h>
 #include <pthread.h>
-#include <pwd.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -63,7 +61,6 @@ int do_shutdown;
 int disabled_passwd;
 int disabled_group;
 int go_background = 1;
-const char *server_user;
 
 int secure[lastdb];
 int secure_in_use;
@@ -71,7 +68,6 @@ static const char *conffile = _PATH_NSCDCONF;
 
 static int check_pid (const char *file);
 static int write_pid (const char *file);
-static void drop_privileges (void);
 
 /* Name and version of program.  */
 static void print_version (FILE *stream, struct argp_state *state);
@@ -169,10 +165,6 @@ main (int argc, char **argv)
   /* Init databases.  */
   nscd_init (conffile);
 
-  /* Change to unprivileged UID if specifed in config file */
-  if(server_user && !secure_in_use)
-    drop_privileges ();
-
   /* Handle incoming requests */
   start_threads ();
 
@@ -373,36 +365,3 @@ write_pid (const char *file)
 
   return 0;
 }
-
-/* Look up the uid and gid associated with the user we are supposed to run
-   the server as, and then call setgid(), setgroups(), and setuid().
-   Otherwise, abort- we should not run as root if the configuration file
-   specifically tells us not to. */
-
-static void
-drop_privileges (void)
-{
-  int buflen = 256;
-  char *buffer = alloca (buflen);
-  struct passwd resultbuf;
-  struct passwd *pwd;
-
-  while (__getpwnam_r (server_user, &resultbuf, buffer, buflen, &pwd) != 0
-	 && errno == ERANGE)
-    {
-      errno = 0;
-      buflen += 256;
-      buffer = alloca (buflen);
-    }
-
-  if(!pwd)
-    {
-      dbg_log (_("Failed to look up user '%s' to run server as"),
-	       server_user);
-      exit(1);
-    }
-
-  setgroups (0, NULL);
-  setgid (pwd->pw_gid);
-  setuid (pwd->pw_uid);
-}
diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h
index da9a5d3279..1dc225ed4b 100644
--- a/sysdeps/mips/dl-machine.h
+++ b/sysdeps/mips/dl-machine.h
@@ -276,8 +276,8 @@ __dl_runtime_resolve (ElfW(Word) sym_index,				      \
     = (const void *) D_PTR (l, l_info[DT_SYMTAB]);			      \
   const char *strtab							      \
     = (const void *) D_PTR (l, l_info[DT_STRTAB]);			      \
-  const ElfW(Addr) *got							      \
-    = (const ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]);		      \
+  ElfW(Addr) *got							      \
+    = (ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]);			      \
   const ElfW(Word) local_gotno						      \
     = (const ElfW(Word)) l->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val;	      \
   const ElfW(Word) gotsym						      \