From 459c2d0f8152715eedf75af1fb9d7f6a429ede85 Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Feb 06 2010 10:09:15 +0000 Subject: - avoid accessing unrelated mount points in disk space checking (#547548) --- diff --git a/rpm-4.8.0-lazy-statfs.patch b/rpm-4.8.0-lazy-statfs.patch new file mode 100644 index 0000000..35b4320 --- /dev/null +++ b/rpm-4.8.0-lazy-statfs.patch @@ -0,0 +1,271 @@ +diff --git a/lib/transaction.c b/lib/transaction.c +index 1860dfb..d913258 100644 +--- a/lib/transaction.c ++++ b/lib/transaction.c +@@ -45,6 +45,7 @@ + #include "debug.h" + + struct diskspaceInfo_s { ++ char * mntPoint; /*!< File system mount point */ + dev_t dev; /*!< File system device number. */ + int64_t bneeded; /*!< No. of blocks needed. */ + int64_t ineeded; /*!< No. of inodes needed. */ +@@ -61,83 +62,114 @@ struct diskspaceInfo_s { + + static int rpmtsInitDSI(const rpmts ts) + { +- rpmDiskSpaceInfo dsi; +- struct stat sb; +- int rc; +- int i; +- + if (rpmtsFilterFlags(ts) & RPMPROB_FILTER_DISKSPACE) + return 0; +- +- rpmlog(RPMLOG_DEBUG, "mounted filesystems:\n"); +- rpmlog(RPMLOG_DEBUG, +- " i dev bsize bavail iavail mount point\n"); +- +- rc = rpmGetFilesystemList(&ts->filesystems, &ts->filesystemCount); +- if (rc || ts->filesystems == NULL || ts->filesystemCount <= 0) +- return rc; +- +- /* Get available space on mounted file systems. */ +- + ts->dsi = _free(ts->dsi); +- ts->dsi = xcalloc((ts->filesystemCount + 1), sizeof(*ts->dsi)); ++ ts->filesystemCount = 0; ++ ts->dsi = xcalloc(1, sizeof(*ts->dsi)); ++ return 0; ++} + +- dsi = ts->dsi; ++static rpmDiskSpaceInfo rpmtsCreateDSI(const rpmts ts, dev_t dev, ++ const char * dirName, int count) ++{ ++ rpmDiskSpaceInfo dsi; ++ struct stat sb; ++ char * resolved_path; ++ char mntPoint[PATH_MAX]; ++ int rc; + +- if (dsi != NULL) +- for (i = 0; (i < ts->filesystemCount) && dsi; i++, dsi++) { + #if STATFS_IN_SYS_STATVFS +- struct statvfs sfb; +- memset(&sfb, 0, sizeof(sfb)); +- rc = statvfs(ts->filesystems[i], &sfb); ++ struct statvfs sfb; ++ memset(&sfb, 0, sizeof(sfb)); ++ rc = statvfs(dirName, &sfb); + #else +- struct statfs sfb; +- memset(&sfb, 0, sizeof(sfb)); ++ struct statfs sfb; ++ memset(&sfb, 0, sizeof(sfb)); + # if STAT_STATFS4 + /* This platform has the 4-argument version of the statfs call. The last two + * should be the size of struct statfs and 0, respectively. The 0 is the + * filesystem type, and is always 0 when statfs is called on a mounted + * filesystem, as we're doing. + */ +- rc = statfs(ts->filesystems[i], &sfb, sizeof(sfb), 0); ++ rc = statfs(dirName, &sfb, sizeof(sfb), 0); + # else +- rc = statfs(ts->filesystems[i], &sfb); ++ rc = statfs(dirName, &sfb); + # endif + #endif +- if (rc) +- break; +- +- rc = stat(ts->filesystems[i], &sb); +- if (rc) +- break; +- dsi->dev = sb.st_dev; +- +- dsi->bsize = sfb.f_bsize; +- dsi->bneeded = 0; +- dsi->ineeded = 0; ++ if (rc) ++ return NULL; ++ ++ rc = stat(dirName, &sb); ++ if (rc) ++ return NULL; ++ if (sb.st_dev != dev) // XXX WHY? ++ return NULL; ++ ++ ts->dsi = xrealloc(ts->dsi, (count + 2) * sizeof(*ts->dsi)); ++ dsi = ts->dsi + count; ++ memset(dsi, 0, 2 * sizeof(*dsi)); ++ ++ dsi->dev = sb.st_dev; ++ dsi->bsize = sfb.f_bsize; ++ if (!dsi->bsize) ++ dsi->bsize = 512; /* we need a bsize */ ++ dsi->bneeded = 0; ++ dsi->ineeded = 0; + #ifdef STATFS_HAS_F_BAVAIL +- dsi->bavail = (sfb.f_flag & ST_RDONLY) ? 0 : sfb.f_bavail; ++ dsi->bavail = (sfb.f_flag & ST_RDONLY) ? 0 : sfb.f_bavail; + #else + /* FIXME: the statfs struct doesn't have a member to tell how many blocks are + * available for non-superusers. f_blocks - f_bfree is probably too big, but + * it's about all we can do. + */ +- dsi->bavail = sfb.f_blocks - sfb.f_bfree; ++ dsi->bavail = sfb.f_blocks - sfb.f_bfree; + #endif +- /* XXX Avoid FAT and other file systems that have not inodes. */ +- /* XXX assigning negative value to unsigned type */ +- dsi->iavail = !(sfb.f_ffree == 0 && sfb.f_files == 0) +- ? sfb.f_ffree : -1; +- rpmlog(RPMLOG_DEBUG, +- "%5d 0x%08x %8" PRId64 " %12" PRId64 " %12" PRId64" %s\n", +- i, (unsigned) dsi->dev, dsi->bsize, +- dsi->bavail, dsi->iavail, +- ts->filesystems[i]); ++ /* XXX Avoid FAT and other file systems that have not inodes. */ ++ /* XXX assigning negative value to unsigned type */ ++ dsi->iavail = !(sfb.f_ffree == 0 && sfb.f_files == 0) ++ ? sfb.f_ffree : -1; ++ ++ /* Find mount point belonging to this device number */ ++ resolved_path = realpath(dirName, mntPoint); ++ if (!resolved_path) { ++ strncpy(mntPoint, dirName, PATH_MAX); ++ mntPoint[PATH_MAX-1] = '\0'; + } +- return rc; ++ char * end = NULL; ++ while (end != mntPoint) { ++ end = strrchr(mntPoint, '/'); ++ if (end == mntPoint) { // reached "/" ++ stat("/", &sb); ++ if (dsi->dev != sb.st_dev) { ++ dsi->mntPoint = xstrdup(mntPoint); ++ } else { ++ dsi->mntPoint = xstrdup("/"); ++ } ++ break; ++ } else if (end) { ++ *end = '\0'; ++ } else { // dirName doesn't start with / - should not happen ++ dsi->mntPoint = xstrdup(dirName); ++ break; ++ } ++ stat(mntPoint, &sb); ++ if (dsi->dev != sb.st_dev) { ++ *end = '/'; ++ dsi->mntPoint = xstrdup(mntPoint); ++ break; ++ } ++ } ++ ++ rpmlog(RPMLOG_DEBUG, ++ "0x%08x %8" PRId64 " %12" PRId64 " %12" PRId64" %s\n", ++ (unsigned) dsi->dev, dsi->bsize, ++ dsi->bavail, dsi->iavail, ++ dsi->mntPoint); ++ return dsi; + } + +-static void rpmtsUpdateDSI(const rpmts ts, dev_t dev, ++static void rpmtsUpdateDSI(const rpmts ts, dev_t dev, const char *dirName, + rpm_loff_t fileSize, rpm_loff_t prevSize, rpm_loff_t fixupSize, + rpmFileAction action) + { +@@ -148,8 +180,10 @@ static void rpmtsUpdateDSI(const rpmts ts, dev_t dev, + if (dsi) { + while (dsi->bsize && dsi->dev != dev) + dsi++; +- if (dsi->bsize == 0) +- dsi = NULL; ++ if (dsi->bsize == 0) { ++ /* create new entry */ ++ dsi = rpmtsCreateDSI(ts, dev, dirName, dsi - ts->dsi); ++ } + } + if (dsi == NULL) + return; +@@ -192,26 +226,22 @@ static void rpmtsCheckDSIProblems(const rpmts ts, const rpmte te) + rpmDiskSpaceInfo dsi; + rpmps ps; + int fc; +- int i; +- +- if (ts->filesystems == NULL || ts->filesystemCount <= 0) +- return; + + dsi = ts->dsi; +- if (dsi == NULL) ++ if (dsi == NULL || !dsi->bsize) + return; + fc = rpmfiFC(rpmteFI(te)); + if (fc <= 0) + return; + + ps = rpmtsProblems(ts); +- for (i = 0; i < ts->filesystemCount; i++, dsi++) { ++ for (; dsi->bsize; dsi++) { + + if (dsi->bavail >= 0 && adj_fs_blocks(dsi->bneeded) > dsi->bavail) { + if (dsi->bneeded != dsi->obneeded) { + rpmpsAppend(ps, RPMPROB_DISKSPACE, + rpmteNEVRA(te), rpmteKey(te), +- ts->filesystems[i], NULL, NULL, ++ dsi->mntPoint, NULL, NULL, + (adj_fs_blocks(dsi->bneeded) - dsi->bavail) * dsi->bsize); + dsi->obneeded = dsi->bneeded; + } +@@ -221,7 +251,7 @@ static void rpmtsCheckDSIProblems(const rpmts ts, const rpmte te) + if (dsi->ineeded != dsi->oineeded) { + rpmpsAppend(ps, RPMPROB_DISKNODES, + rpmteNEVRA(te), rpmteKey(te), +- ts->filesystems[i], NULL, NULL, ++ dsi->mntPoint, NULL, NULL, + (adj_fs_blocks(dsi->ineeded) - dsi->iavail)); + dsi->oineeded = dsi->ineeded; + } +@@ -230,6 +260,20 @@ static void rpmtsCheckDSIProblems(const rpmts ts, const rpmte te) + ps = rpmpsFree(ps); + } + ++static void rpmtsFreeDSI(rpmts ts){ ++ rpmDiskSpaceInfo dsi; ++ if (ts == NULL) ++ return; ++ dsi = ts->dsi; ++ while (dsi && dsi->bsize != 0) { ++ dsi->mntPoint = _free(dsi->mntPoint); ++ dsi++; ++ } ++ ++ ts->dsi = _free(ts->dsi); ++} ++ ++ + /** + */ + static int archOkay(const char * pkgArch) +@@ -543,8 +587,9 @@ assert(otherFi != NULL); + } + + /* Update disk space info for a file. */ +- rpmtsUpdateDSI(ts, fiFps->entry->dev, rpmfiFSize(fi), +- rpmfiFReplacedSize(fi), fixupSize, rpmfsGetAction(fs, i)); ++ rpmtsUpdateDSI(ts, fiFps->entry->dev, fiFps->entry->dirName, ++ rpmfiFSize(fi), rpmfiFReplacedSize(fi), ++ fixupSize, rpmfsGetAction(fs, i)); + + } + ps = rpmpsFree(ps); +@@ -1338,6 +1383,7 @@ static int rpmtsPrepare(rpmts ts) + exit: + ht = rpmFpHashFree(ht); + fpc = fpCacheFree(fpc); ++ rpmtsFreeDSI(ts); + return rc; + } + diff --git a/rpm.spec b/rpm.spec index 5c81544..29696e5 100644 --- a/rpm.spec +++ b/rpm.spec @@ -46,6 +46,7 @@ Patch200: rpm-4.8.0-url-segfault.patch Patch201: rpm-4.8.0-verify-exitcode.patch Patch202: rpm-4.8.0-pythondeps-parallel.patch Patch203: rpm-4.8.0-python-bytecompile.patch +Patch204: rpm-4.8.0-lazy-statfs.patch # These are not yet upstream Patch301: rpm-4.6.0-niagara.patch @@ -197,6 +198,7 @@ packages on a system. %patch201 -p1 -b .verify-exitcode %patch202 -p1 -b .pythondeps-parallel %patch203 -p1 -b .python-bytecompile +%patch204 -p1 -b .lazy-statfs %patch301 -p1 -b .niagara %patch302 -p1 -b .geode @@ -415,6 +417,7 @@ exit 0 %changelog * Fri Feb 05 2010 Panu Matilainen - 4.8.0-8 - more fixes to postscript provides extractor (#562228) +- avoid accessing unrelated mount points in disk space checking (#547548) * Fri Feb 05 2010 Panu Matilainen - 4.8.0-7 - couple of fixes to the postscript provides extractor (#538101)