fa3bfd
Mostly equivalent upstream commit:
fa3bfd
fa3bfd
commit 0699f766b10c86912b75f35bef697106b70c1cf6
fa3bfd
Author: Carlos O'Donell <carlos@redhat.com>
fa3bfd
Date:   Thu Apr 10 18:31:53 2014 -0400
fa3bfd
fa3bfd
    nscd: Make SELinux checks dynamic.
fa3bfd
12745e
diff --git glibc-2.17-c758a686/nscd/selinux.c glibc-2.17-c758a686/nscd/selinux.c
29e444
index 0866c44..ba55b04 100644
12745e
--- glibc-2.17-c758a686/nscd/selinux.c
12745e
+++ glibc-2.17-c758a686/nscd/selinux.c
29e444
@@ -44,35 +44,31 @@
29e444
 /* Global variable to tell if the kernel has SELinux support.  */
29e444
 int selinux_enabled;
29e444
 
29e444
-/* Define mappings of access vector permissions to request types.  */
29e444
-static const access_vector_t perms[LASTREQ] =
29e444
+/* Define mappings of request type to AVC permission name.  */
29e444
+static const char *perms[LASTREQ] =
29e444
 {
29e444
-  [GETPWBYNAME] = NSCD__GETPWD,
29e444
-  [GETPWBYUID] = NSCD__GETPWD,
29e444
-  [GETGRBYNAME] = NSCD__GETGRP,
29e444
-  [GETGRBYGID] = NSCD__GETGRP,
29e444
-  [GETHOSTBYNAME] = NSCD__GETHOST,
29e444
-  [GETHOSTBYNAMEv6] = NSCD__GETHOST,
29e444
-  [GETHOSTBYADDR] = NSCD__GETHOST,
29e444
-  [GETHOSTBYADDRv6] = NSCD__GETHOST,
29e444
-  [GETSTAT] = NSCD__GETSTAT,
29e444
-  [SHUTDOWN] = NSCD__ADMIN,
29e444
-  [INVALIDATE] = NSCD__ADMIN,
29e444
-  [GETFDPW] = NSCD__SHMEMPWD,
29e444
-  [GETFDGR] = NSCD__SHMEMGRP,
29e444
-  [GETFDHST] = NSCD__SHMEMHOST,
29e444
-  [GETAI] = NSCD__GETHOST,
29e444
-  [INITGROUPS] = NSCD__GETGRP,
29e444
-#ifdef NSCD__GETSERV
29e444
-  [GETSERVBYNAME] = NSCD__GETSERV,
29e444
-  [GETSERVBYPORT] = NSCD__GETSERV,
29e444
-  [GETFDSERV] = NSCD__SHMEMSERV,
29e444
-#endif
29e444
-#ifdef NSCD__GETNETGRP
29e444
-  [GETNETGRENT] = NSCD__GETNETGRP,
29e444
-  [INNETGR] = NSCD__GETNETGRP,
29e444
-  [GETFDNETGR] = NSCD__SHMEMNETGRP,
29e444
-#endif
29e444
+  [GETPWBYNAME] = "getpwd",
29e444
+  [GETPWBYUID] = "getpwd",
29e444
+  [GETGRBYNAME] = "getgrp",
29e444
+  [GETGRBYGID] = "getgrp",
29e444
+  [GETHOSTBYNAME] = "gethost",
29e444
+  [GETHOSTBYNAMEv6] = "gethost",
29e444
+  [GETHOSTBYADDR] = "gethost",
29e444
+  [GETHOSTBYADDRv6] = "gethost",
29e444
+  [SHUTDOWN] = "admin",
29e444
+  [GETSTAT] = "getstat",
29e444
+  [INVALIDATE] = "admin",
29e444
+  [GETFDPW] = "shmempwd",
29e444
+  [GETFDGR] = "shmemgrp",
29e444
+  [GETFDHST] = "shmemhost",
29e444
+  [GETAI] = "gethost",
29e444
+  [INITGROUPS] = "getgrp",
29e444
+  [GETSERVBYNAME] = "getserv",
29e444
+  [GETSERVBYPORT] = "getserv",
29e444
+  [GETFDSERV] = "shmemserv",
29e444
+  [GETNETGRENT] = "getnetgrp",
29e444
+  [INNETGR] = "getnetgrp",
29e444
+  [GETFDNETGR] = "shmemnetgrp",
29e444
 };
29e444
 
29e444
 /* Store an entry ref to speed AVC decisions.  */
29e444
@@ -344,7 +340,18 @@ nscd_avc_init (void)
29e444
 
29e444
 
29e444
 /* Check the permission from the caller (via getpeercon) to nscd.
29e444
-   Returns 0 if access is allowed, 1 if denied, and -1 on error.  */
29e444
+   Returns 0 if access is allowed, 1 if denied, and -1 on error.
29e444
+
29e444
+   Implementation note:
29e444
+   The SELinux policy, enablement, and permission bits are all dynamic
29e444
+   and the caching done by glibc is not entirely correct.  This nscd
29e444
+   support should be rewritten to use selinux_check_permission.
29e444
+   A rewrite is risky though and requires some refactoring fist.
29e444
+   Instead we use symbolic mappings instead of compile time
29e444
+   constants (which selinux upstream says are going away), and use
29e444
+   security_deny_unknown to determine what to do if selinux-policy
29e444
+   doesn't have a definition for the the permission or object class
29e444
+   we are looking up.  */
29e444
 int
29e444
 nscd_request_avc_has_perm (int fd, request_type req)
29e444
 {
29e444
@@ -354,6 +361,33 @@ nscd_request_avc_has_perm (int fd, request_type req)
29e444
   security_id_t ssid = NULL;
29e444
   security_id_t tsid = NULL;
29e444
   int rc = -1;
29e444
+  security_class_t sc_nscd = 0;
29e444
+  access_vector_t perm = 0;
29e444
+  int avc_deny_unknown = 0;
29e444
+
29e444
+  /* Check if SELinux denys or allows unknown object classes
29e444
+     and permissions.  It is 0 if they are allowed, 1 if they
29e444
+     are not allowed and -1 on error.  */
29e444
+  if ((avc_deny_unknown = security_deny_unknown ()) == -1)
29e444
+    dbg_log (_("Error querying policy for undefined object classes "
29e444
+	       "or permissions."));
29e444
+
29e444
+  /* Get the security class for nscd.  If this fails we will likely be
29e444
+     unable to do anything unless avc_deny_unknown is 0.  */
29e444
+  if ((sc_nscd = string_to_security_class ("nscd")) == 0
29e444
+      && avc_deny_unknown == 1)
29e444
+    dbg_log (_("Error getting security class for nscd."));
29e444
+
29e444
+  /* Convert permission to AVC bits.  */
29e444
+  perm = string_to_av_perm (sc_nscd, perms[req]);
29e444
+  if (perm == 0 && avc_deny_unknown == 1)
29e444
+      dbg_log (_("Error translating permission name "
29e444
+		 "\"%s\" to access vector bit."), perms[req]);
29e444
+
29e444
+  /* If the nscd security class was not found or perms were not
29e444
+     found and AVC does not deny unknown values then allow it.  */
29e444
+  if ((sc_nscd == 0 || perm == 0) && avc_deny_unknown == 0)
29e444
+    return 0;
29e444
 
29e444
   if (getpeercon (fd, &scon) < 0)
29e444
     {
29e444
@@ -372,15 +406,7 @@ nscd_request_avc_has_perm (int fd, request_type req)
29e444
       goto out;
29e444
     }
29e444
 
29e444
-#ifndef NSCD__GETSERV
29e444
-  if (perms[req] == 0)
29e444
-    {
29e444
-      dbg_log (_("compile-time support for database policy missing"));
29e444
-      goto out;
29e444
-    }
29e444
-#endif
29e444
-
29e444
-  rc = avc_has_perm (ssid, tsid, SECCLASS_NSCD, perms[req], &aeref, NULL) < 0;
29e444
+  rc = avc_has_perm (ssid, tsid, sc_nscd, perm, &aeref, NULL) < 0;
29e444
 
29e444
 out:
29e444
   if (scon)