diff options
3 files changed, 189 insertions, 0 deletions
diff --git a/meta/recipes-devtools/rpm/rpm/rpm-hardlink-segfault-fix.patch b/meta/recipes-devtools/rpm/rpm/rpm-hardlink-segfault-fix.patch new file mode 100644 index 0000000000..8c2a04a3d5 --- /dev/null +++ b/meta/recipes-devtools/rpm/rpm/rpm-hardlink-segfault-fix.patch @@ -0,0 +1,43 @@ +We need to sanity check that the nlink size and our linksLeft counter +do match. If an rpm is badly constructed with identical inode values +for multiple hardlinked files, such an rpm will otherwise access memory +out of array bounds and cause memory corruption and crashes. + +The fix is to add in the sanity check and exit if bad circumstances +are found. We need to fix the caller to check the return code too. + +RP 2014/6/10 + +Upstream-Status: Pending + +Index: rpm-5.4.9/lib/fsm.c +=================================================================== +--- rpm-5.4.9.orig/lib/fsm.c 2014-06-10 10:54:08.601049402 +0000 ++++ rpm-5.4.9/lib/fsm.c 2014-06-10 10:55:45.633046077 +0000 +@@ -495,6 +495,11 @@ + } + + if (fsm->goal == IOSM_PKGBUILD) --fsm->li->linksLeft; ++ if (fsm->li->linksLeft > st->st_nlink) { ++ rpmlog(RPMLOG_ERR, _("Corrupted hardlinks found (count %d does not match %d), exiting.\n"), fsm->li->linksLeft, st->st_nlink); ++ return -1; ++ } ++ + fsm->li->filex[fsm->li->linksLeft] = fsm->ix; + /*@-observertrans -dependenttrans@*/ + fsm->li->nsuffix[fsm->li->linksLeft] = fsm->nsuffix; +@@ -1876,8 +1881,13 @@ + fsm->postpone = iosmFileActionSkipped(fsm->action); + if (fsm->goal == IOSM_PKGINSTALL || fsm->goal == IOSM_PKGBUILD) { + /*@-evalorder@*/ /* FIX: saveHardLink can modify fsm */ +- if (S_ISREG(st->st_mode) && st->st_nlink > 1) ++ if (S_ISREG(st->st_mode) && st->st_nlink > 1) { + fsm->postpone = saveHardLink(fsm); ++ if (fsm->postpone < 0) { ++ rc = RPMRC_FAIL; ++ break; ++ } ++ } + /*@=evalorder@*/ + } + if (fsmGetFi(fsm)->mapflags & IOSM_PAYLOAD_LIST) fsm->postpone = 1; diff --git a/meta/recipes-devtools/rpm/rpm/rpm-payload-use-hashed-inode.patch b/meta/recipes-devtools/rpm/rpm/rpm-payload-use-hashed-inode.patch new file mode 100644 index 0000000000..fc6b218300 --- /dev/null +++ b/meta/recipes-devtools/rpm/rpm/rpm-payload-use-hashed-inode.patch @@ -0,0 +1,144 @@ +If we run builds on a filesystem with 64 bit inodes like XFS, we need to +map the inode numbers to something 32 bit since the cpio header only allows +for 32 bit inode values. If we don't do this: + +#define SET_NUM_FIELD(phys, val, space) \ + sprintf(space, "%8.8lx", (unsigned long) (val)); \ + memcpy(phys, space, 8) + +from cpio.c will print larger that 8 character values and then truncate the +LSBs. This generates cpio files where hardlinked files may have the same +inode number. The resulting rpms are then corrupted. + +There is a separate patch for the crash the identical inode numbers causes +when extracting the rpm. + +Patch taken from http://git.pld-linux.org/?p=packages/rpm.git;a=commitdiff;h=10526c23aac60b7b636e4c93862887dbef8e8f15 + +RP 2014/6/10 + +Upstream-Status: Pending + +diff -ur rpm-5.4.10/build/files.c rpm-5.4.10-collision/build/files.c +--- rpm-5.4.10/build/files.c 2013-03-17 13:17:38.233358389 +0100 ++++ rpm-5.4.10-collision/build/files.c 2013-03-17 13:07:37.468483625 +0100 +@@ -1323,6 +1323,26 @@ + return dalgo; + } + ++static int isHardLink(FileListRec flp, FileListRec tlp) ++{ ++ return ((S_ISREG(flp->fl_mode) && S_ISREG(tlp->fl_mode)) && ++ ((flp->fl_nlink > 1) && (flp->fl_nlink == tlp->fl_nlink)) && ++ (flp->fl_ino == tlp->fl_ino) && ++ (flp->fl_dev == tlp->fl_dev)); ++} ++ ++static int seenHardLink(FileList fl, FileListRec flp, ino_t *fileid) ++{ ++ FileListRec ilp; ++ for (ilp = fl->fileList; ilp < flp; ilp++) { ++ if (isHardLink(flp, ilp)) { ++ *fileid = ilp - fl->fileList; ++ return 1; ++ } ++ } ++ return 0; ++} ++ + /** + * Add file entries to header. + * @todo Should directories have %doc/%config attributes? (#14531) +@@ -1370,6 +1390,7 @@ + + for (i = 0, flp = fl->fileList; i < fl->fileListRecsUsed; i++, flp++) { + const char *s; ++ ino_t fileid = flp - fl->fileList; + + /* Merge duplicate entries. */ + while (i < (fl->fileListRecsUsed - 1) && +@@ -1437,6 +1458,13 @@ + /* Leave room for both dirname and basename NUL's */ + dpathlen += (strlen(flp->diskURL) + 2); + ++ /* Excludes and dupes have been filtered out by now. */ ++ if (S_ISREG(flp->fl_mode)) { ++ if (flp->fl_nlink == 1 || !seenHardLink(fl, flp, &fileid)) { ++ fl->totalFileSize += flp->fl_size; ++ } ++ } ++ + /* + * Make the header, the OLDFILENAMES will get converted to a + * compressed file list write before we write the actual package to +@@ -1519,7 +1547,11 @@ + + /* XXX Hash instead of 64b->32b truncate to prevent aliasing. */ + { ino_t _ino = flp->fl_ino; +- ui32 = hashFunctionString(0, &_ino, sizeof(_ino)); ++ /* don't use hash here, as hash collisions which happen on large packages ++ cause bus errors in rpmbuild ++ ui32 = hashFunctionString(0, &_ino, sizeof(_ino)); ++ */ ++ ui32 = fileid + 1; + } + he->tag = RPMTAG_FILEINODES; + he->t = RPM_UINT32_TYPE; +@@ -1752,39 +1780,6 @@ + IOSM_MAP_TYPE | IOSM_MAP_MODE | IOSM_MAP_UID | IOSM_MAP_GID; + if (isSrc) + fi->fmapflags[i] |= IOSM_FOLLOW_SYMLINKS; +- +- if (S_ISREG(flp->fl_mode)) { +- int bingo = 1; +- /* Hard links need be tallied only once. */ +- if (flp->fl_nlink > 1) { +- FileListRec jlp = flp + 1; +- int j = i + 1; +- for (; (unsigned)j < fi->fc; j++, jlp++) { +- /* follow outer loop logic */ +- while (((jlp - fl->fileList) < (fl->fileListRecsUsed - 1)) && +- !strcmp(jlp->fileURL, jlp[1].fileURL)) +- jlp++; +- if (jlp->flags & RPMFILE_EXCLUDE) { +- j--; +- /*@innercontinue@*/ continue; +- } +- if (jlp->flags & RPMFILE_GHOST) +- /*@innercontinue@*/ continue; +- if (!S_ISREG(jlp->fl_mode)) +- /*@innercontinue@*/ continue; +- if (flp->fl_nlink != jlp->fl_nlink) +- /*@innercontinue@*/ continue; +- if (flp->fl_ino != jlp->fl_ino) +- /*@innercontinue@*/ continue; +- if (flp->fl_dev != jlp->fl_dev) +- /*@innercontinue@*/ continue; +- bingo = 0; /* don't tally hardlink yet. */ +- /*@innerbreak@*/ break; +- } +- } +- if (bingo) +- fl->totalFileSize += flp->fl_size; +- } + } + + ui32 = fl->totalFileSize; +--- rpm-5.4.10/lib/fsm.c~ ++++ rpm-5.4.10/lib/fsm.c +@@ -898,6 +898,7 @@ int fsmMapAttrs(IOSM_t fsm) + + if (fi && i >= 0 && i < (int) fi->fc) { + mode_t perms = (S_ISDIR(st->st_mode) ? fi->dperms : fi->fperms); ++ ino_t finalInode = (fi->finodes ? (ino_t)fi->finodes[i] : 0); + mode_t finalMode = (fi->fmodes ? (mode_t)fi->fmodes[i] : perms); + dev_t finalRdev = (dev_t)(fi->frdevs ? fi->frdevs[i] : 0); + rpmuint32_t finalMtime = (fi->fmtimes ? fi->fmtimes[i] : 0); +@@ -937,6 +938,7 @@ int fsmMapAttrs(IOSM_t fsm) + if ((S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) + && st->st_nlink == 0) + st->st_nlink = 1; ++ st->st_ino = finalInode; + st->st_rdev = finalRdev; + st->st_mtime = finalMtime; + } diff --git a/meta/recipes-devtools/rpm/rpm_5.4.9.bb b/meta/recipes-devtools/rpm/rpm_5.4.9.bb index 43f46ed024..690d8b423a 100644 --- a/meta/recipes-devtools/rpm/rpm_5.4.9.bb +++ b/meta/recipes-devtools/rpm/rpm_5.4.9.bb @@ -91,6 +91,8 @@ SRC_URI = "http://www.rpm5.org/files/rpm/rpm-5.4/rpm-5.4.9-0.20120508.src.rpm;ex file://rpm-lsb-compatibility.patch \ file://rpm-tag-generate-endian-conversion-fix.patch \ file://rpm-verify-files.patch \ + file://rpm-hardlink-segfault-fix.patch \ + file://rpm-payload-use-hashed-inode.patch \ " # Uncomment the following line to enable platform score debugging |