The following commit has been merged in the master branch:
commit 866f5d2a9702da7b4e809b89c3f7df6933e97116
Author: Guillem Jover <[email protected]>
Date:   Sun Nov 11 00:25:31 2012 +0100

    dpkg: Reload the SELinux label database if it has changed
    
    Rework the code to use the selabel API instead of the matchpathcon
    wrappers, so that we can query if the label database has changed
    during the previous unpack, for example while upgrading the SELinux
    policy package. This also allows us to more easily free the resources
    allocated for the label database.

diff --git a/debian/changelog b/debian/changelog
index 415cfb3..c99c0d6 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -54,6 +54,8 @@ dpkg (1.17.0) UNRELEASED; urgency=low
   * Refer to path instead of file on dpkg-statoverride.
   * Always print a descriptive architecture column, even for empty or missing
     architectures on «dpkg-query --list».
+  * Rework SELinux code on unpack to reload the label database if it has
+    changed, for example while upgrading the SELinux policy package.
 
  -- Guillem Jover <[email protected]>  Fri, 03 Aug 2012 13:21:00 +0200
 
diff --git a/src/archives.c b/src/archives.c
index 783719c..b59e10b 100644
--- a/src/archives.c
+++ b/src/archives.c
@@ -59,6 +59,8 @@
 
 #ifdef WITH_SELINUX
 #include <selinux/selinux.h>
+#include <selinux/avc.h>
+#include <selinux/label.h>
 #endif
 
 #include "filesdb.h"
@@ -476,11 +478,71 @@ tarobject_set_perms(struct tar_entry *te, const char 
*path, struct file_stat *st
   }
 }
 
+#ifdef WITH_SELINUX
+static struct selabel_handle *dpkg_sehandle;
+
+static struct selabel_handle *
+dpkg_selabel_get_handle(void)
+{
+  return dpkg_sehandle;
+}
+#endif
+
 static void
-tarobject_set_se_context(const char *matchpath, const char *path, mode_t mode)
+dpkg_selabel_load(void)
 {
 #ifdef WITH_SELINUX
   static int selinux_enabled = -1;
+
+  if (selinux_enabled < 0) {
+    int rc;
+
+    /* Set selinux_enabled if it is not already set (singleton). */
+    selinux_enabled = (is_selinux_enabled() > 0);
+    if (!selinux_enabled)
+      return;
+
+    /* Open the SELinux status notification channel, with fallback enabled
+     * for older kernels. */
+    rc = selinux_status_open(1);
+    if (rc < 0)
+      ohshit(_("cannot open security status notification channel"));
+
+    /* XXX: We could use selinux_set_callback() to redirect the errors from
+     * the other SELinux calls, but that does not seem worth it right now. */
+  } else if (selinux_enabled && selinux_status_updated()) {
+    /* The SELinux policy got updated in the kernel, usually after upgrading
+     * the package shipping it, we need to reload. */
+    selabel_close(dpkg_sehandle);
+  } else {
+    /* SELinux is either disabled or it does not need a reload. */
+    return;
+  }
+
+  dpkg_sehandle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
+  if (dpkg_sehandle == NULL)
+    ohshite(_("cannot get security labeling handle"));
+#endif
+}
+
+static void
+dpkg_selabel_close(void)
+{
+#ifdef WITH_SELINUX
+  if (dpkg_sehandle == NULL)
+    return;
+
+  selinux_status_close();
+  selabel_close(dpkg_sehandle);
+  dpkg_sehandle = NULL;
+#endif
+}
+
+static void
+tarobject_set_se_context(const char *matchpath, const char *path, mode_t mode)
+{
+#ifdef WITH_SELINUX
+  struct selabel_handle *sehandle;
   security_context_t scontext = NULL;
   int ret;
 
@@ -488,26 +550,20 @@ tarobject_set_se_context(const char *matchpath, const 
char *path, mode_t mode)
   if ((mode & S_IFMT) == 0)
     return;
 
-  /* Set selinux_enabled if it is not already set (singleton). */
-  if (selinux_enabled < 0) {
-    selinux_enabled = (is_selinux_enabled() > 0);
-
-    /* Do not translate from computer to human readable forms, to avoid
-     * issues when mcstransd has disappeared during the unpack process. */
-    if (selinux_enabled)
-      set_matchpathcon_flags(MATCHPATHCON_NOTRANS);
-  }
-
-  /* If SE Linux is not enabled just do nothing. */
-  if (!selinux_enabled)
+  /* If SELinux is not enabled just do nothing. */
+  sehandle = dpkg_selabel_get_handle();
+  if (sehandle == NULL)
     return;
 
-  /* XXX: Well, we could use set_matchpathcon_printf() to redirect the
-   * errors from the following bit, but that seems too much effort. */
+  /*
+   * We use the _raw function variants here so that no translation happens
+   * from computer to human readable forms, to avoid issues when mcstransd
+   * has disappeared during the unpack process.
+   */
 
   /* Do nothing if we can't figure out what the context is, or if it has
    * no context; in which case the default context shall be applied. */
-  ret = matchpathcon(matchpath, mode & S_IFMT, &scontext);
+  ret = selabel_lookup_raw(sehandle, &scontext, matchpath, mode & S_IFMT);
   if (ret == -1 || (ret == 0 && scontext == NULL))
     return;
 
@@ -1590,6 +1646,8 @@ archivefiles(const char *const *argv)
     }
     push_error_context_jump(&ejbuf, print_error_perpackage, thisarg);
 
+    dpkg_selabel_load();
+
     process_archive(thisarg);
     onerr_abort++;
     m_output(stdout, _("<standard output>"));
@@ -1599,6 +1657,8 @@ archivefiles(const char *const *argv)
     pop_error_context(ehflag_normaltidy);
   }
 
+  dpkg_selabel_close();
+
   switch (cipaction->arg_int) {
   case act_install:
   case act_configure:

-- 
dpkg's main repository


-- 
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]

Reply via email to