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.14/lib/fsm.c =================================================================== --- rpm-5.4.14.orig/lib/fsm.c +++ rpm-5.4.14/lib/fsm.c @@ -495,6 +495,11 @@ static int saveHardLink(/*@special@*/ /* } 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; @@ -1878,8 +1883,13 @@ if (!(fsmGetFi(fsm)->mapflags & IOSM_PAY 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;