| 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; |