selinux: reopen label between transactions if necessary (RhBug: 746073)
authorAles Kozumplik <akozumpl@redhat.com>
Thu, 22 Dec 2011 13:34:03 +0000 (14:34 +0100)
committerAles Kozumplik <akozumpl@redhat.com>
Thu, 12 Jan 2012 13:27:36 +0000 (14:27 +0100)
lib/rpmts.c
lib/rpmts_internal.h
lib/transaction.c
plugins/sepolicy.c
system.h

index 25ce83d..8641149 100644 (file)
@@ -738,19 +738,28 @@ struct selabel_handle * rpmtsSELabelHandle(rpmts ts)
     return NULL;
 }
 
-rpmRC rpmtsSELabelInit(rpmts ts, const char *path)
+rpmRC rpmtsSELabelInit(rpmts ts, int open_status, const char *path)
 {
 #if WITH_SELINUX
     if (ts == NULL || path == NULL) {
        return RPMRC_FAIL;
     }
 
+    if (open_status) {
+       selinux_status_close();
+       if (selinux_status_open(0) < 0) {
+           return RPMRC_FAIL;
+       }
+    } else if (!selinux_status_updated() && ts->selabelHandle) {
+       return RPMRC_OK;
+    }
+
     struct selinux_opt opts[] = {
        {SELABEL_OPT_PATH, path}
     };
 
     if (ts->selabelHandle) {
-       rpmtsSELabelFini(ts);
+       rpmtsSELabelFini(ts, 0);
     }
     ts->selabelHandle = selabel_open(SELABEL_CTX_FILE, opts, 1);
 
@@ -761,13 +770,16 @@ rpmRC rpmtsSELabelInit(rpmts ts, const char *path)
     return RPMRC_OK;
 }
 
-void rpmtsSELabelFini(rpmts ts)
+void rpmtsSELabelFini(rpmts ts, int close_status)
 {
 #if WITH_SELINUX
     if (ts && ts->selabelHandle) {
        selabel_close(ts->selabelHandle);
        ts->selabelHandle = NULL;
     }
+    if (close_status) {
+       selinux_status_close();
+    }
 #endif
 }
 
index 438fd46..b4213fe 100644 (file)
@@ -70,7 +70,7 @@ struct rpmts_s {
 #ifdef __cplusplus
 extern "C" {
 #endif
+
 RPM_GNUC_INTERNAL
 tsMembers rpmtsMembers(rpmts ts);
 
@@ -91,16 +91,18 @@ struct selabel_handle * rpmtsSELabelHandle(rpmts ts);
 /** \ingroup rpmts
  * Initialize selabel
  * @param ts           transaction set
+ * @param open_status   if the func should open selinux status or just check it
  * @param path         path to contexts file
  * @return             RPMRC_OK on success, RPMRC_FAIL otherwise
  */
-rpmRC rpmtsSELabelInit(rpmts ts, const char * path);
+rpmRC rpmtsSELabelInit(rpmts ts, int open_status, const char * path);
 
 /** \ingroup rpmts
  * Clean up selabel
  * @param ts           transaction set
+ * @param close_status  whether we should close selinux status
  */
-void rpmtsSELabelFini(rpmts ts);
+void rpmtsSELabelFini(rpmts ts, int close_status);
 
 #ifdef __cplusplus
 }
index 88219b7..da2895b 100644 (file)
@@ -1253,13 +1253,18 @@ static int rpmtsSetup(rpmts ts, rpmprobFilterFlags ignoreSet)
     if (rpmtsFlags(ts) & (RPMTRANS_FLAG_JUSTDB | RPMTRANS_FLAG_TEST))
        (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers | RPMTRANS_FLAG_NOCOLLECTIONS));
 
-    /* if SELinux isn't enabled, init fails or test run, don't bother... */
+    /* if SELinux isn't enabled or it is a test run, don't bother... */
     if (!is_selinux_enabled() || (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) {
         rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_NOCONTEXTS));
     }
 
-    if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) {
-       rpmtsSELabelInit(ts, selinux_file_context_path());
+    if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS) {
+       rpmlog(RPMLOG_DEBUG, "Selinux disabled.\n");
+    } else {
+       if (rpmtsSELabelInit(ts, 1, selinux_file_context_path())) {
+           rpmlog(RPMLOG_WARNING, "Failed to open SELinux handle.\n");
+           rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_NOCONTEXTS));
+       }
     }
 
     /* 
@@ -1283,7 +1288,7 @@ static int rpmtsSetup(rpmts ts, rpmprobFilterFlags ignoreSet)
 static int rpmtsFinish(rpmts ts)
 {
     if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) {
-       rpmtsSELabelFini(ts);
+       rpmtsSELabelFini(ts, 1);
     }
     return rpmChrootSet(NULL);
 }
@@ -1384,6 +1389,10 @@ static int rpmtsProcess(rpmts ts)
        rpmlog(RPMLOG_DEBUG, "========== +++ %s %s-%s 0x%x\n",
                rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
 
+       if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) {
+           rpmtsSELabelInit(ts, 0, selinux_file_context_path());
+       }
+
        failed = rpmteProcess(p, rpmteType(p));
        if (failed) {
            rpmlog(RPMLOG_ERR, "%s: %s %s\n", rpmteNEVRA(p),
index 2916415..adbbd13 100644 (file)
@@ -556,7 +556,7 @@ static rpmRC sepolGo(void)
     /* re-init selinux and re-read the files contexts, since things may have changed */
     selinux_reset_config();
     if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) {
-       if (rpmtsSELabelInit(ts, selinux_file_context_path()) == RPMRC_OK) {
+       if (rpmtsSELabelInit(ts, 0, selinux_file_context_path()) == RPMRC_OK) {
            /* if this was the first time installing policy, every package before
             * policy was installed will be mislabeled (e.g. semodule). So, relabel
             * the entire filesystem if this is the case */
index 9b23e45..dd35738 100644 (file)
--- a/system.h
+++ b/system.h
@@ -79,6 +79,7 @@ char * stpncpy(char * dest, const char * src, size_t n);
 #if WITH_SELINUX
 #include <selinux/selinux.h>
 #include <selinux/label.h>
+#include <selinux/avc.h>
 #else
 typedef        char * security_context_t;