fix: prevent segfault if malicious server sends 1 GB of data through ftpNLST.
[platform/upstream/rpm.git] / lib / transaction.c
index 56d395d..d019de4 100644 (file)
 
 #include "debug.h"
 
-/*@access FD_t @*/             /* XXX compared with NULL */
-/*@access Header @*/           /* XXX compared with NULL */
+/*@access Header @*/           /* XXX ts->notify arg1 is void ptr */
 /*@access rpmps @*/    /* XXX need rpmProblemSetOK() */
 /*@access dbiIndexSet @*/
-/*@access rpmdb @*/
 
 /*@access rpmpsm @*/
 
@@ -161,7 +159,7 @@ static fileAction decideFileFate(const rpmts ts,
        if (oFLink && nFLink && !strcmp(oFLink, nFLink))
            return FA_SKIP;     /* identical file, don't bother. */
 /*@=nullpass@*/
-     }
+    }
 
     /*
      * The config file on the disk has been modified, but
@@ -215,6 +213,9 @@ static int handleInstInstalledFiles(const rpmts ts,
        /*@globals rpmGlobalMacroContext, fileSystem, internalState @*/
        /*@modifies ts, fi, rpmGlobalMacroContext, fileSystem, internalState @*/
 {
+    uint_32 tscolor = rpmtsColor(ts);
+    uint_32 otecolor, tecolor;
+    uint_32 oficolor, ficolor;
     const char * altNEVR = NULL;
     rpmfi otherFi = NULL;
     int numReplaced = 0;
@@ -235,6 +236,18 @@ static int handleInstInstalledFiles(const rpmts ts,
        mi = rpmdbFreeIterator(mi);
     }
 
+    /* Compute package color. */
+    tecolor = rpmteColor(p);
+    tecolor &= tscolor;
+
+    /* Compute other pkg color. */
+    otecolor = 0;
+    otherFi = rpmfiInit(otherFi, 0);
+    if (otherFi != NULL)
+    while (rpmfiNext(otherFi) >= 0)
+       otecolor |= rpmfiFColor(otherFi);
+    otecolor &= tscolor;
+
     if (otherFi == NULL)
        return 1;
 
@@ -247,9 +260,13 @@ static int handleInstInstalledFiles(const rpmts ts,
 
        otherFileNum = shared->otherFileNum;
        (void) rpmfiSetFX(otherFi, otherFileNum);
+       oficolor = rpmfiFColor(otherFi);
+       oficolor &= tscolor;
 
        fileNum = shared->pkgFileNum;
        (void) rpmfiSetFX(fi, fileNum);
+       ficolor = rpmfiFColor(fi);
+       ficolor &= tscolor;
 
        isCfgFile = ((rpmfiFFlags(otherFi) | rpmfiFFlags(fi)) & RPMFILE_CONFIG);
 
@@ -263,6 +280,8 @@ static int handleInstInstalledFiles(const rpmts ts,
            continue;
 
        if (filecmp(otherFi, fi)) {
+           /* Report conflicts only for packages/files of same color. */
+           if (tscolor == 0 || (tecolor == otecolor && ficolor == oficolor))
            if (reportConflicts) {
                rpmpsAppend(ps, RPMPROB_FILE_CONFLICT,
                        rpmteNEVR(p), rpmteKey(p),
@@ -604,7 +623,7 @@ static void handleOverlappedFiles(const rpmts ts,
 
 assert(otherFi != NULL);
            /* Mark added overlapped non-identical files as a conflict. */
-           if ((rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACENEWFILES)
+           if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACENEWFILES)
             && filecmp(otherFi, fi))
            {
                rpmpsAppend(ps, RPMPROB_NEW_FILE_CONFLICT,
@@ -661,8 +680,8 @@ assert(otherFi != NULL);
 /*@=boundswrite@*/
 
        /* Update disk space info for a file. */
-       rpmtsUpdateDSI(ts, fiFps->entry->dev,
-                rpmfiFSize(fi), fi->replacedSizes[i], fixupSize, fi->actions[i]);
+       rpmtsUpdateDSI(ts, fiFps->entry->dev, rpmfiFSize(fi),
+               fi->replacedSizes[i], fixupSize, fi->actions[i]);
 
     }
     ps = rpmpsFree(ps);
@@ -722,6 +741,9 @@ static int ensureOlder(rpmts ts,
 }
 
 /**
+ * Skip any files that do not match install policies.
+ * @param ts           transaction set
+ * @param fi           file info set
  */
 /*@-mustmod@*/ /* FIX: fi->actions is modified. */
 /*@-bounds@*/
@@ -729,6 +751,9 @@ static void skipFiles(const rpmts ts, rpmfi fi)
        /*@globals rpmGlobalMacroContext @*/
        /*@modifies fi, rpmGlobalMacroContext @*/
 {
+    uint_32 tscolor = rpmtsColor(ts);
+    uint_32 ficolor;
+    int noConfigs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONFIGS);
     int noDocs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NODOCS);
     char ** netsharedPaths = NULL;
     const char ** languages;
@@ -773,7 +798,7 @@ static void skipFiles(const rpmts ts, rpmfi fi)
     if (fi != NULL)    /* XXX lclint */
     while ((i = rpmfiNext(fi)) >= 0)
     {
-       char **nsp;
+       char ** nsp;
 
        bn = rpmfiBN(fi);
        bnlen = strlen(bn);
@@ -787,7 +812,15 @@ static void skipFiles(const rpmts ts, rpmfi fi)
 
        /* Don't bother with skipped files */
        if (XFA_SKIPPING(fi->actions[i])) {
-           drc[ix]--;
+           drc[ix]--; dff[ix] = 1;
+           continue;
+       }
+
+       /* Ignore colored files not in our rainbow. */
+       ficolor = rpmfiFColor(fi);
+       if (tscolor && ficolor && !(tscolor & ficolor)) {
+           drc[ix]--;  dff[ix] = 1;
+           fi->actions[i] = FA_SKIPCOLOR;
            continue;
        }
 
@@ -831,7 +864,7 @@ static void skipFiles(const rpmts ts, rpmfi fi)
        /*
         * Skip i18n language specific files.
         */
-       if (fi->flangs && languages && *fi->flangs[i]) {
+       if (languages != NULL && fi->flangs != NULL && *fi->flangs[i]) {
            const char **lang, *l, *le;
            for (lang = languages; *lang != NULL; lang++) {
                if (!strcmp(*lang, "all"))
@@ -854,6 +887,15 @@ static void skipFiles(const rpmts ts, rpmfi fi)
        }
 
        /*
+        * Skip config files if requested.
+        */
+       if (noConfigs && (rpmfiFFlags(fi) & RPMFILE_CONFIG)) {
+           drc[ix]--;  dff[ix] = 1;
+           fi->actions[i] = FA_SKIPNSTATE;
+           continue;
+       }
+
+       /*
         * Skip documentation if requested.
         */
        if (noDocs && (rpmfiFFlags(fi) & RPMFILE_DOC)) {
@@ -915,11 +957,13 @@ static void skipFiles(const rpmts ts, rpmfi fi)
        }
     }
 
+/*@-dependenttrans@*/
     if (netsharedPaths) freeSplitString(netsharedPaths);
 #ifdef DYING   /* XXX freeFi will deal with this later. */
     fi->flangs = _free(fi->flangs);
 #endif
     if (languages) freeSplitString((char **)languages);
+/*@=dependenttrans@*/
 }
 /*@=bounds@*/
 /*@=mustmod@*/
@@ -954,6 +998,7 @@ rpmfi rpmtsiFi(const rpmtsi tsi)
 
 int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
 {
+    uint_32 tscolor = rpmtsColor(ts);
     int i, j;
     int ourrc = 0;
     int totalFileCount = 0;
@@ -971,15 +1016,16 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
     int numRemoved;
     int xx;
 
-    /* FIXME: what if the same package is included in ts twice? */
+    /* XXX programmer error segfault avoidance. */
+    if (rpmtsNElements(ts) <= 0)
+       return -1;
 
     if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOSCRIPTS)
        (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers));
     if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERS)
        (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransTriggers));
 
-    /* XXX MULTILIB is broken, as packages can and do execute /sbin/ldconfig. */
-    if (rpmtsFlags(ts) & (RPMTRANS_FLAG_JUSTDB | RPMTRANS_FLAG_MULTILIB))
+    if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)
        (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers));
 
     ts->probs = rpmpsFree(ts->probs);
@@ -1018,7 +1064,7 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
      * - count files.
      */
 
-rpmMessage(RPMMESS_DEBUG, _("sanity checking %d elments\n"), rpmtsNElements(ts));
+rpmMessage(RPMMESS_DEBUG, _("sanity checking %d elements\n"), rpmtsNElements(ts));
     ps = rpmtsProblems(ts);
     /* The ordering doesn't matter here */
     pi = rpmtsiInit(ts);
@@ -1030,7 +1076,7 @@ rpmMessage(RPMMESS_DEBUG, _("sanity checking %d elments\n"), rpmtsNElements(ts))
            continue;   /* XXX can't happen */
        fc = rpmfiFC(fi);
 
-       if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREARCH))
+       if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREARCH) && !tscolor)
            if (!archOkay(rpmteA(p)))
                rpmpsAppend(ps, RPMPROB_BADARCH,
                        rpmteNEVR(p), rpmteKey(p),
@@ -1052,8 +1098,7 @@ rpmMessage(RPMMESS_DEBUG, _("sanity checking %d elments\n"), rpmtsNElements(ts))
            mi = rpmdbFreeIterator(mi);
        }
 
-       /* XXX multilib should not display "already installed" problems */
-       if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEPKG) && !rpmteMultiLib(p)) {
+       if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEPKG)) {
            mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0);
            xx = rpmdbSetIteratorRE(mi, RPMTAG_EPOCH, RPMMIRE_DEFAULT,
                                rpmteE(p));
@@ -1061,6 +1106,12 @@ rpmMessage(RPMMESS_DEBUG, _("sanity checking %d elments\n"), rpmtsNElements(ts))
                                rpmteV(p));
            xx = rpmdbSetIteratorRE(mi, RPMTAG_RELEASE, RPMMIRE_DEFAULT,
                                rpmteR(p));
+           if (tscolor) {
+               xx = rpmdbSetIteratorRE(mi, RPMTAG_ARCH, RPMMIRE_DEFAULT,
+                               rpmteA(p));
+               xx = rpmdbSetIteratorRE(mi, RPMTAG_OS, RPMMIRE_DEFAULT,
+                               rpmteO(p));
+           }
 
            while (rpmdbNextIterator(mi) != NULL) {
                rpmpsAppend(ps, RPMPROB_PKG_INSTALLED,
@@ -1102,6 +1153,7 @@ rpmMessage(RPMMESS_DEBUG, _("sanity checking %d elments\n"), rpmtsNElements(ts))
      * worth the trouble though.
      */
 rpmMessage(RPMMESS_DEBUG, _("computing %d file fingerprints\n"), totalFileCount);
+
     numAdded = numRemoved = 0;
     pi = rpmtsiInit(ts);
     while ((p = rpmtsiNext(pi, 0)) != NULL) {
@@ -1151,10 +1203,13 @@ rpmMessage(RPMMESS_DEBUG, _("computing %d file fingerprints\n"), totalFileCount)
     while ((p = rpmtsiNext(pi, 0)) != NULL) {
        int fc;
 
+       (void) rpmdbCheckSignals();
+
        if ((fi = rpmtsiFi(pi)) == NULL)
            continue;   /* XXX can't happen */
        fc = rpmfiFC(fi);
 
+       (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
        fpLookupList(fpc, fi->dnl, fi->bnl, fi->dil, fc, fi->fps);
        /*@-branchstate@*/
        fi = rpmfiInit(fi, 0);
@@ -1167,6 +1222,8 @@ rpmMessage(RPMMESS_DEBUG, _("computing %d file fingerprints\n"), totalFileCount)
            /*@=dependenttrans@*/
        }
        /*@=branchstate@*/
+       (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);
+
     }
     pi = rpmtsiFree(pi);
 
@@ -1184,6 +1241,8 @@ rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
        int knownBad;
        int fc;
 
+       (void) rpmdbCheckSignals();
+
        if ((fi = rpmtsiFi(pi)) == NULL)
            continue;   /* XXX can't happen */
        fc = rpmfiFC(fi);
@@ -1193,6 +1252,7 @@ rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
 
        if (fc == 0) continue;
 
+       (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
        /* Extract file info for all files in this package from the database. */
        matches = xcalloc(fc, sizeof(*matches));
        if (rpmdbFindFpList(rpmtsGetRdb(ts), fi->fps, matches, fc)) {
@@ -1292,6 +1352,7 @@ rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
        case TR_REMOVED:
            /*@switchbreak@*/ break;
        }
+       (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);
     }
     pi = rpmtsiFree(pi);
     ps = rpmpsFree(ps);
@@ -1341,9 +1402,13 @@ rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
      */
     if (rpmtsFlags(ts) & (RPMTRANS_FLAG_DIRSTASH | RPMTRANS_FLAG_REPACKAGE)) {
        int progress;
+
        progress = 0;
        pi = rpmtsiInit(ts);
        while ((p = rpmtsiNext(pi, 0)) != NULL) {
+
+           (void) rpmdbCheckSignals();
+
            if ((fi = rpmtsiFi(pi)) == NULL)
                continue;       /* XXX can't happen */
            switch (rpmteType(p)) {
@@ -1357,9 +1422,11 @@ rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
                                7, numRemoved, NULL, ts->notifyData));
 
                NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_PROGRESS, progress,
-                        numRemoved, NULL, ts->notifyData));
+                       numRemoved, NULL, ts->notifyData));
                progress++;
 
+               (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
+
        /* XXX TR_REMOVED needs CPIO_MAP_{ABSOLUTE,ADDDOT} CPIO_ALL_HARDLINKS */
                fi->mapflags |= CPIO_MAP_ABSOLUTE;
                fi->mapflags |= CPIO_MAP_ADDDOT;
@@ -1371,6 +1438,8 @@ rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
                fi->mapflags &= ~CPIO_MAP_ADDDOT;
                fi->mapflags &= ~CPIO_ALL_HARDLINKS;
 
+               (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
+
                /*@switchbreak@*/ break;
            }
        }
@@ -1391,16 +1460,20 @@ rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
        alKey pkgKey;
        int gotfd;
 
+       (void) rpmdbCheckSignals();
+
        gotfd = 0;
        if ((fi = rpmtsiFi(pi)) == NULL)
            continue;   /* XXX can't happen */
        
        psm = rpmpsmNew(ts, p, fi);
+assert(psm != NULL);
        psm->unorderedSuccessor =
                (rpmtsiOc(pi) >= rpmtsUnorderedSuccessors(ts, -1) ? 1 : 0);
 
        switch (rpmteType(p)) {
        case TR_ADDED:
+           (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_INSTALL), 0);
 
            pkgKey = rpmteAddedKey(p);
 
@@ -1432,6 +1505,8 @@ rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
                        p->fd = NULL;
                        ourrc++;
                        /*@innerbreak@*/ break;
+                   case RPMRC_NOTTRUSTED:
+                   case RPMRC_NOKEY:
                    case RPMRC_OK:
                        /*@innerbreak@*/ break;
                    }
@@ -1449,11 +1524,18 @@ rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
                {
                    char * fstates = fi->fstates;
                    fileAction * actions = fi->actions;
+                   rpmte savep;
 
                    fi->fstates = NULL;
                    fi->actions = NULL;
+/*@-nullstate@*/ /* FIX: fi->actions is NULL */
                    fi = rpmfiFree(fi);
+/*@=nullstate@*/
+
+                   savep = rpmtsSetRelocateElement(ts, p);
                    fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, 1);
+                   (void) rpmtsSetRelocateElement(ts, savep);
+
                    if (fi != NULL) {   /* XXX can't happen */
                        fi->te = p;
                        fi->fstates = _free(fi->fstates);
@@ -1465,11 +1547,6 @@ rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
                }
                psm->fi = rpmfiLink(p->fi, NULL);
 
-               if (rpmteMultiLib(p))
-                   (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_MULTILIB));
-               else
-                   (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) & ~RPMTRANS_FLAG_MULTILIB));
-
 /*@-nullstate@*/ /* FIX: psm->fi may be NULL */
                if (rpmpsmStage(psm, PSM_PKGINSTALL)) {
                    ourrc++;
@@ -1493,8 +1570,13 @@ rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
 
            p->h = headerFree(p->h);
 
+           (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_INSTALL), 0);
+
            /*@switchbreak@*/ break;
+
        case TR_REMOVED:
+           (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_ERASE), 0);
+
            rpmMessage(RPMMESS_DEBUG, "========== --- %s\n", rpmteNEVR(p));
            /*
             * XXX This has always been a hack, now mostly broken.
@@ -1504,6 +1586,9 @@ rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
                if (rpmpsmStage(psm, PSM_PKGERASE))
                    ourrc++;
            }
+
+           (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_ERASE), 0);
+
            /*@switchbreak@*/ break;
        }
        xx = rpmdbSync(rpmtsGetRdb(ts));