diff options
author | David Kalnischkies <david@kalnischkies.de> | 2015-11-20 00:54:07 +0100 |
---|---|---|
committer | David Kalnischkies <david@kalnischkies.de> | 2015-11-20 00:54:07 +0100 |
commit | 6789e01e9370b3b7f65d52138c5657eaa712b4d1 (patch) | |
tree | cf0b9282cae981271918512f7af62da7dda4e64c /apt-pkg | |
parent | 520624d562e54e8e2c0191fae723e668e3ece6b4 (diff) |
do not segfault in cache generation on mmap failure
Out of memory and similar circumstanzas could cause MMap::Map to fail
and especially the mmap/malloc calls in it. With some additional
checking we can avoid segfaults and similar in such situations – at
least in theory as if this is a real out of memory everything we do to
handle the error could just as well run into a memory problem as well…
But at least in theory (if MMap::Map is made to fail always) we can deal
with it so good that a user actually never sees a failure (as the cache
it tries to load with it fails and is discarded, so that DynamicMMap
takes over and a new one is build) instead of segfaulting.
Closes: 803417
Diffstat (limited to 'apt-pkg')
-rw-r--r-- | apt-pkg/cachefile.cc | 2 | ||||
-rw-r--r-- | apt-pkg/contrib/mmap.cc | 15 | ||||
-rw-r--r-- | apt-pkg/pkgcachegen.cc | 10 |
3 files changed, 21 insertions, 6 deletions
diff --git a/apt-pkg/cachefile.cc b/apt-pkg/cachefile.cc index aaa2436c5..39f1e72db 100644 --- a/apt-pkg/cachefile.cc +++ b/apt-pkg/cachefile.cc @@ -80,6 +80,8 @@ bool pkgCacheFile::BuildCaches(OpProgress *Progress, bool WithLock) if (file.IsOpen() == false || file.Failed()) return false; Map = new MMap(file, MMap::Public|MMap::ReadOnly); + if (unlikely(Map->validData() == false)) + return false; Cache = new pkgCache(Map); return _error->PendingError() == false; } diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc index 8e169027e..33c33d1c1 100644 --- a/apt-pkg/contrib/mmap.cc +++ b/apt-pkg/contrib/mmap.cc @@ -38,7 +38,7 @@ // --------------------------------------------------------------------- /* */ MMap::MMap(FileFd &F,unsigned long Flags) : Flags(Flags), iSize(0), - Base(0), SyncToFd(NULL) + Base(nullptr), SyncToFd(nullptr) { if ((Flags & NoImmMap) != NoImmMap) Map(F); @@ -48,7 +48,7 @@ MMap::MMap(FileFd &F,unsigned long Flags) : Flags(Flags), iSize(0), // --------------------------------------------------------------------- /* */ MMap::MMap(unsigned long Flags) : Flags(Flags), iSize(0), - Base(0), SyncToFd(NULL) + Base(nullptr), SyncToFd(nullptr) { } /*}}}*/ @@ -84,6 +84,8 @@ bool MMap::Map(FileFd &Fd) if ((Flags & ReadOnly) != ReadOnly) return _error->Error("Compressed file %s can only be mapped readonly", Fd.Name().c_str()); Base = malloc(iSize); + if (unlikely(Base == nullptr)) + return _error->Errno("MMap-compressed-malloc", _("Couldn't make mmap of %llu bytes"), iSize); SyncToFd = new FileFd(); if (Fd.Seek(0L) == false || Fd.Read(Base, iSize) == false) return _error->Error("Compressed file %s can't be read into mmap", Fd.Name().c_str()); @@ -92,7 +94,7 @@ bool MMap::Map(FileFd &Fd) // Map it. Base = (Flags & Fallback) ? MAP_FAILED : mmap(0,iSize,Prot,Map,Fd.Fd(),0); - if (Base == (void *)-1) + if (Base == MAP_FAILED) { if (errno == ENODEV || errno == EINVAL || (Flags & Fallback)) { @@ -102,6 +104,8 @@ bool MMap::Map(FileFd &Fd) { // for readonly, we don't need sync, so make it simple Base = malloc(iSize); + if (unlikely(Base == nullptr)) + return _error->Errno("MMap-malloc", _("Couldn't make mmap of %llu bytes"), iSize); SyncToFd = new FileFd(); return Fd.Read(Base, iSize); } @@ -111,13 +115,14 @@ bool MMap::Map(FileFd &Fd) return _error->Errno("mmap", _("Couldn't duplicate file descriptor %i"), Fd.Fd()); Base = calloc(iSize, 1); + if (unlikely(Base == nullptr)) + return _error->Errno("MMap-calloc", _("Couldn't make mmap of %llu bytes"), iSize); SyncToFd = new FileFd (dupped_fd); if (!SyncToFd->Seek(0L) || !SyncToFd->Read(Base, iSize)) return false; } else - return _error->Errno("mmap",_("Couldn't make mmap of %llu bytes"), - iSize); + return _error->Errno("MMap-mmap", _("Couldn't make mmap of %llu bytes"), iSize); } return true; diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 5c61ff2b8..e1958f45a 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -125,7 +125,7 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) : advoid a problem during a crash */ pkgCacheGenerator::~pkgCacheGenerator() { - if (_error->PendingError() == true) + if (_error->PendingError() == true || Map.validData() == false) return; if (Map.Sync() == false) return; @@ -1307,6 +1307,8 @@ static bool CheckValidity(const string &CacheFile, // Map it FileFd CacheF(CacheFile,FileFd::ReadOnly); std::unique_ptr<MMap> Map(new MMap(CacheF,0)); + if (unlikely(Map->validData()) == false) + return false; pkgCache Cache(Map.get()); if (_error->PendingError() || Map->Size() == 0) { @@ -1539,6 +1541,8 @@ static bool loadBackMMapFromFile(std::unique_ptr<pkgCacheGenerator> &Gen, std::unique_ptr<DynamicMMap> &Map, OpProgress * const Progress, std::string const &FileName) { Map.reset(CreateDynamicMMap(NULL, 0)); + if (unlikely(Map->validData()) == false) + return false; FileFd CacheF(FileName, FileFd::ReadOnly); if (CacheF.IsOpen() == false || CacheF.Failed()) return false; @@ -1628,6 +1632,8 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress // At this point we know we need to construct something, so get storage ready std::unique_ptr<DynamicMMap> Map(CreateDynamicMMap(NULL, 0)); + if (unlikely(Map->validData()) == false) + return false; if (Debug == true) std::clog << "Open memory Map (not filebased)" << std::endl; @@ -1716,6 +1722,8 @@ bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **O ScopedErrorMerge sem; std::unique_ptr<DynamicMMap> Map(CreateDynamicMMap(NULL, 0)); + if (unlikely(Map->validData()) == false) + return false; map_filesize_t CurrentSize = 0; map_filesize_t TotalSize = 0; TotalSize = ComputeSize(NULL, Files.begin(), Files.end()); |