summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeitor R. Alves de Siqueira <halves@canonical.com>2019-02-08 13:05:18 +0100
committerJulian Andres Klode <julian.klode@canonical.com>2019-02-08 13:05:18 +0100
commit22e3f5d3e311bc001a05803fcf39036f620b1d96 (patch)
tree92e111713b6c2deb0375f86d295aaa5767a45b7a
parent5d07bad6105eb1b7c158c502fe89803e120be064 (diff)
backport "do not segfault in cache generation on mmap failure"
Original commit message: 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 LP: #1815129
-rw-r--r--apt-pkg/cachefile.cc2
-rw-r--r--apt-pkg/contrib/mmap.cc11
-rw-r--r--apt-pkg/pkgcachegen.cc10
3 files changed, 18 insertions, 5 deletions
diff --git a/apt-pkg/cachefile.cc b/apt-pkg/cachefile.cc
index 96bcdc097..622d38367 100644
--- a/apt-pkg/cachefile.cc
+++ b/apt-pkg/cachefile.cc
@@ -67,6 +67,8 @@ bool pkgCacheFile::BuildCaches(OpProgress *Progress, bool WithLock)
{
Map = new MMap(*new FileFd(_config->FindFile("Dir::Cache::pkgcache"),
FileFd::ReadOnly),MMap::Public|MMap::ReadOnly);
+ if (unlikely(Map->validData() == false))
+ return false;
Cache = new pkgCache(Map);
if (_error->PendingError() == true)
return false;
diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc
index b2a53a6cb..f82537afb 100644
--- a/apt-pkg/contrib/mmap.cc
+++ b/apt-pkg/contrib/mmap.cc
@@ -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 == NULL))
+ 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 == NULL))
+ 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 == NULL))
+ 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 810f0b022..11e529d41 100644
--- a/apt-pkg/pkgcachegen.cc
+++ b/apt-pkg/pkgcachegen.cc
@@ -59,7 +59,7 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) :
CurrentFile = 0;
memset(UniqHash,0,sizeof(UniqHash));
- if (_error->PendingError() == true)
+ if (_error->PendingError() == true || Map.validData() == false)
return;
if (Map.Size() == 0)
@@ -1181,6 +1181,8 @@ static bool CheckValidity(const string &CacheFile,
// Map it
FileFd CacheF(CacheFile,FileFd::ReadOnly);
SPtr<MMap> Map = new MMap(CacheF,0);
+ if (unlikely(Map->validData() == false))
+ return false;
pkgCache Cache(Map);
if (_error->PendingError() == true || Map->Size() == 0)
{
@@ -1425,7 +1427,7 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress
CacheF = new FileFd(CacheFile,FileFd::WriteAtomic);
fchmod(CacheF->Fd(),0644);
Map = CreateDynamicMMap(CacheF, MMap::Public);
- if (_error->PendingError() == true)
+ if (_error->PendingError() == true || Map->validData() == false)
{
delete CacheF.UnGuard();
delete Map.UnGuard();
@@ -1450,6 +1452,8 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress
{
// Just build it in memory..
Map = CreateDynamicMMap(NULL);
+ if (unlikely(Map->validData() == false))
+ return false;
if (Debug == true)
std::clog << "Open memory Map (not filebased)" << std::endl;
}
@@ -1556,6 +1560,8 @@ bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **O
return false;
SPtr<DynamicMMap> Map = CreateDynamicMMap(NULL);
+ if (unlikely(Map->validData() == false))
+ return false;
unsigned long CurrentSize = 0;
unsigned long TotalSize = 0;