Rather than using the PSM to extract policy from headers, as we did in
previous patchsets, we now call rpmtsPreparePolicy which performs the
necessary preparations. Currently this only includes creating rpmpol
structures for each transaction element. In later patchsets, this
will include logic to determine how to handle different policy actions
(e.g. install, upgrade, remove, etc.).

This also adds the --nopolicy option to disable installing policy.
---
 lib/poptI.c          |    2 +
 lib/rpmte.c          |   28 ++++++++++
 lib/rpmte.h          |   15 ++++++
 lib/rpmte_internal.h |    3 +
 lib/rpmts.h          |    1 +
 lib/transaction.c    |  138 +++++++++++++++++++++++++++++++++++++++++++++++++-
 6 files changed, 186 insertions(+), 1 deletions(-)

diff --git a/lib/poptI.c b/lib/poptI.c
index f460f96..8ead1eb 100644
--- a/lib/poptI.c
+++ b/lib/poptI.c
@@ -205,6 +205,8 @@ struct poptOption rpmInstallPoptTable[] = {
        N_("don't verify digest of files (obsolete)"), NULL },
  { "nocontexts", '\0',0,  NULL, RPMCLI_POPT_NOCONTEXTS,
        N_("don't install file security contexts"), NULL},
+ { "nopolicy", '\0', POPT_BIT_SET, &rpmIArgs.transFlags, 
RPMTRANS_FLAG_NOPOLICY,
+       N_("don't install selinux policy modules"), NULL},
 
  { "noorder", '\0', POPT_BIT_SET,
        &rpmIArgs.installInterfaceFlags, INSTALL_NOORDER,
diff --git a/lib/rpmte.c b/lib/rpmte.c
index f25af12..e53c41d 100644
--- a/lib/rpmte.c
+++ b/lib/rpmte.c
@@ -10,6 +10,7 @@
 #include <rpm/rpmfi.h>
 #include <rpm/rpmts.h>
 #include <rpm/rpmdb.h>
+#include <rpm/rpmpol.h>
 
 #include "lib/rpmte_internal.h"
 
@@ -52,6 +53,7 @@ struct rpmte_s {
     rpmds conflicts;           /*!< Conflicts: dependencies. */
     rpmds obsoletes;           /*!< Obsoletes: dependencies. */
     rpmfi fi;                  /*!< File information. */
+    rpmpol pol;                /*!< Policies */
     rpmps probs;               /*!< Problems (relocations) */
 
     rpm_color_t color;         /*!< Color bit(s) from package dependencies. */
@@ -66,6 +68,7 @@ struct rpmte_s {
 #define RPMTE_HAVE_POSTTRANS   (1 << 1)
     int transscripts;          /*!< pre/posttrans script existence */
     int failed;                        /*!< (parent) install/erase failed */
+    int policies;              /*!< policy existence */
 
     rpmfs fs;
 };
@@ -113,6 +116,7 @@ static void delTE(rpmte p)
     p->h = headerFree(p->h);
     p->fs = rpmfsFree(p->fs);
     p->probs = rpmpsFree(p->probs);
+    p->pol = rpmpolFree(p->pol);
 
     memset(p, 0, sizeof(*p));  /* XXX trash and burn */
     /* FIX: p->{NEVR,name} annotations */
@@ -278,6 +282,9 @@ static void addTE(rpmts ts, rpmte p, Header h,
     }
     p->fi = getFI(p, ts, h);
 
+    p->policies = headerIsEntry(h, RPMTAG_POLICIES);
+    p->pol = NULL;
+
     /* See if we have pre/posttrans scripts. */
     p->transscripts |= (headerIsEntry(h, RPMTAG_PRETRANS) &&
                         headerIsEntry(h, RPMTAG_PRETRANSPROG)) ?
@@ -628,6 +635,22 @@ rpmfi rpmteFI(rpmte te)
     return te->fi; /* XXX take fi reference here? */
 }
 
+rpmpol rpmteSetPol(rpmte te, rpmpol pol)
+{
+       if (te != NULL) {
+               te->pol = rpmpolFree(te->pol);
+               if (pol != NULL) {
+                       te->pol = rpmpolLink(pol);
+               }
+       }
+       return NULL;
+}
+
+rpmpol rpmtePol(rpmte te)
+{
+       return (te == NULL) ? NULL : te->pol;
+}
+
 void rpmteColorDS(rpmte te, rpmTag tag)
 {
     rpmfi fi = rpmteFI(te);
@@ -887,6 +910,11 @@ rpmps rpmteProblems(rpmte te)
     return te ? te->probs : NULL;
 }
 
+int rpmteHavePolicies(rpmte te)
+{
+    return (te != NULL && te->policies);
+}
+
 rpmfs rpmteGetFileStates(rpmte te) {
     return te->fs;
 }
diff --git a/lib/rpmte.h b/lib/rpmte.h
index 15853e8..06e7d2a 100644
--- a/lib/rpmte.h
+++ b/lib/rpmte.h
@@ -359,6 +359,21 @@ rpmds rpmteDS(rpmte te, rpmTag tag);
 rpmfi rpmteFI(rpmte te);
 
 /** \ingroup rpmte
+ * Set the policy set of a transaction element.
+ * @param te           transaction element
+ * @param pol          policy set
+ * @return             policy set on success, NULL otherwise
+ */
+rpmpol rpmteSetPol(rpmte te, rpmpol pol);
+
+/** \ingroup rpmte
+ * Retrieve policy set from transaction element.
+ * @param te           transaction element
+ * @return             policy set
+ */
+rpmpol rpmtePol(rpmte te);
+
+/** \ingroup rpmte
  * Calculate transaction element dependency colors/refs from file info.
  * @param te           transaction element
  * @param tag          dependency tag (RPMTAG_PROVIDENAME, RPMTAG_REQUIRENAME)
diff --git a/lib/rpmte_internal.h b/lib/rpmte_internal.h
index 060405d..90e1bcb 100644
--- a/lib/rpmte_internal.h
+++ b/lib/rpmte_internal.h
@@ -89,6 +89,9 @@ int rpmteHaveTransScript(rpmte te, rpmTag tag);
 RPM_GNUC_INTERNAL
 rpmps rpmteProblems(rpmte te);
 
+RPM_GNUC_INTERNAL
+int rpmteHavePolicies(rpmte te);
+
 //RPM_GNUC_INTERNAL
 rpmfs rpmteGetFileStates(rpmte te);
 
diff --git a/lib/rpmts.h b/lib/rpmts.h
index 215b28e..cbf11bf 100644
--- a/lib/rpmts.h
+++ b/lib/rpmts.h
@@ -56,6 +56,7 @@ typedef enum rpmtransFlags_e {
     RPMTRANS_FLAG_NOPAYLOAD    = (1 << 24),
     RPMTRANS_FLAG_APPLYONLY    = (1 << 25),
 
+    RPMTRANS_FLAG_NOPOLICY             = (1 << 26),    /*!< from --nopolicy */
     RPMTRANS_FLAG_NOMD5                = (1 << 27),    /*!< from --nomd5 */
     RPMTRANS_FLAG_NOFILEDIGEST = (1 << 27),    /*!< from --nofiledigest (alias 
to --nomd5) */
     RPMTRANS_FLAG_NOSUGGEST    = (1 << 28),    /*!< from --nosuggest */
diff --git a/lib/transaction.c b/lib/transaction.c
index 1ccabcd..bffc105 100644
--- a/lib/transaction.c
+++ b/lib/transaction.c
@@ -9,6 +9,7 @@
 #include <rpm/rpmlog.h>
 #include <rpm/rpmdb.h>
 #include <rpm/rpmds.h>
+#include <rpm/rpmpol.h>
 #include <rpm/rpmfileutil.h>
 #include <rpm/rpmstring.h>
 #include <rpm/argv.h>
@@ -885,6 +886,133 @@ static int runTransScripts(rpmts ts, rpmTag stag)
     return 0;
 }
 
+/*
+ * Clean up everything created in rpmtsPreparePolicy
+ */
+static rpmRC rpmtsFreePolicy(rpmts ts)
+{
+       rpmtsi pi;
+       rpmte p;
+
+       pi = rpmtsiInit(ts);
+       while ((p = rpmtsiNext(pi, TR_ADDED))) {
+               if (!rpmteHavePolicies(p)) {
+                       continue;
+               }
+               rpmteSetPol(p, NULL);
+       }
+       pi = rpmtsiFree(pi);
+
+       return RPMRC_OK;
+}
+
+/*
+ * Create rpmol structures for each transaction element
+ */
+static rpmRC rpmtsPreparePolicy(rpmts ts)
+{
+       rpmtsi pi;
+       rpmte p;
+       rpmpol pol;
+       Header h;
+       int rc = RPMRC_OK;
+       int changes = 0;
+
+       pi = rpmtsiInit(ts);
+       while (rc == RPMRC_OK && (p = rpmtsiNext(pi, TR_ADDED))) {
+               if (!rpmteHavePolicies(p)) {
+                       continue;
+               }
+
+               if (!rpmteOpen(p, ts, 0)) {
+                       rc = RPMRC_FAIL;
+               } else {
+                       h = rpmteHeader(p);
+
+                       pol = rpmpolNew(h);
+                       if (!pol) {
+                               rc = RPMRC_FAIL;
+                       } else {
+                               rpmteSetPol(p, pol);
+                               pol = rpmpolFree(pol);
+                               changes = 1;
+                       }
+
+                       h = headerFree(h);
+                       rpmteClose(p, ts, 0);
+               }
+       }
+       pi = rpmtsiFree(pi);
+
+       if (rc != RPMRC_OK) {
+               rpmtsFreePolicy(ts);
+       }
+       else if (changes == 0) {
+               rc = RPMRC_NOTFOUND;
+       }
+
+       return rc;
+}
+
+/*
+ * Extract and load selinux policy for transaction set
+ * param ts    Transaction set
+ * return      0 on success, -1 on error (invalid script tag)
+ */
+static int rpmtsLoadPolicy(rpmts ts)
+{
+       rpmtsi pi;
+       rpmte p;
+       rpmpol pol;
+       int rc = RPMRC_OK;
+
+       rc = rpmtsPreparePolicy(ts);
+       if (rc == RPMRC_NOTFOUND) {
+               return RPMRC_OK;
+       } else if (rc != RPMRC_OK) {
+               return rc;
+       }
+
+       rpmpoltrans ptrans = rpmpoltransBegin();
+       if (!ptrans) {
+               rpmlog(RPMLOG_ERR, _("Failed to begin policy transaction\n"));
+               return RPMRC_FAIL;
+       }
+
+       pi = rpmtsiInit(ts);
+       while ((p = rpmtsiNext(pi, TR_ADDED))) {
+               if (!rpmteHavePolicies(p)) {
+                       continue;
+               }
+
+               pol = rpmtePol(p);
+               if (!pol) {
+                       rc = RPMRC_FAIL;
+                       goto out;
+               }
+
+               rpmpolInitIterator(pol);
+               while (rpmpolNext(pol) >= 0) {
+                       rc = rpmpoltransAdd(ptrans, pol);
+                       if (rc != RPMRC_OK) {
+                               goto out;
+                       }
+               }
+       }
+out:
+       pi = rpmtsiFree(pi);
+
+       if (rc == RPMRC_OK) {
+               rc = rpmpoltransCommit(ptrans);
+       }
+
+       ptrans = rpmpoltransFree(ptrans);
+
+       rpmtsFreePolicy(ts);
+
+       return rc;
+}
+
 /* Add fingerprint for each file not skipped. */
 static void addFingerprints(rpmts ts, uint64_t fileCount, rpmFpHash ht, 
fingerPrintCache fpc)
 {
@@ -963,7 +1091,7 @@ static int rpmtsSetup(rpmts ts, rpmprobFilterFlags 
ignoreSet)
 
     /* if SELinux isn't enabled or init fails, don't bother... */
     if (!rpmtsSELinuxEnabled(ts)) {
-        rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_NOCONTEXTS));
+        rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_NOCONTEXTS | 
RPMTRANS_FLAG_NOPOLICY));
     }
 
     if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) {
@@ -1176,6 +1304,14 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags 
ignoreSet)
     /* Check package set for problems */
     ts->probs = checkProblems(ts);
 
+    if (!((rpmtsFlags(ts) & 
(RPMTRANS_FLAG_BUILD_PROBS|RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_NOPOLICY))
+         || (rpmpsNumProblems(ts->probs) &&
+               (okProbs == NULL || rpmpsTrim(ts->probs, okProbs))))) {
+               if (rpmtsLoadPolicy(ts) != RPMRC_OK) {
+                       goto exit;
+               }
+       }
+
     /* Run pre-transaction scripts, but only if there are no known
      * problems up to this point and not disabled otherwise. */
     if (!((rpmtsFlags(ts) & 
(RPMTRANS_FLAG_BUILD_PROBS|RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_NOPRE))
-- 
1.6.0.6

_______________________________________________
Rpm-maint mailing list
Rpm-maint@lists.rpm.org
http://lists.rpm.org/mailman/listinfo/rpm-maint

Reply via email to