From 094ae9562beb8686e0e259dbdb2a25e23785fe39 Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Mar 25 2020 08:22:21 +0000 Subject: Fix segfault on fingerprinting symlink round (RhBug:1660232) Both yum and dnf perform a test-transaction before the real thing, and both neglet to check for an error code from the test-transaction when there are no problem objects to return. Which can happen in some special cases, such a using different vsflags between initial package read and transaction (which is what both yum and dnf do), which can cause the in-transaction package open fail on corrupt packages. And when this failed transaction is fed back to rpmtsRun(), it segfaults in fingerprinting as the second loop of symlink checking doesn't check for NULL's element files like the first loop does. Add the missing NULL check and remove bogus "can't happen" comment to fix. FWIW, the scenario with different vsflags and corrupted packages doesn't happen by default in rpm >= 4.14.2, the corrupt package gets caught in the verify stage which does create problem objects and thus both yum and dnf abort as they should. --- diff --git a/lib/fprint.c b/lib/fprint.c index b810e4d..ab18919 100644 --- a/lib/fprint.c +++ b/lib/fprint.c @@ -488,7 +488,7 @@ void fpCachePopulate(fingerPrintCache fpc, rpmts ts, int fileCount) (void) rpmsqPoll(); if ((fi = rpmteFiles(p)) == NULL) - continue; /* XXX can't happen */ + continue; (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); rpmfilesFpLookup(fi, fpc); @@ -522,6 +522,9 @@ void fpCachePopulate(fingerPrintCache fpc, rpmts ts, int fileCount) while ((p = rpmtsiNext(pi, 0)) != NULL) { (void) rpmsqPoll(); + if ((fi = rpmteFiles(p)) == NULL) + continue; + fs = rpmteGetFileStates(p); fc = rpmfsFC(fs); (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); @@ -531,6 +534,7 @@ void fpCachePopulate(fingerPrintCache fpc, rpmts ts, int fileCount) fpLookupSubdir(symlinks, fpc, p, i); } (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); + rpmfilesFree(fi); } rpmtsiFree(pi);