8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-02-02 10:00:38 +01:00

Avoid the 4GB shmem limit overflow causing a crash

This commit is contained in:
Dmitry Yemanov 2023-07-21 18:05:36 +03:00
parent e6685c7b25
commit d7e0d49b86
2 changed files with 30 additions and 22 deletions

View File

@ -100,7 +100,10 @@ namespace
private:
TempSpace& tempSpace;
};
}
const ULONG HEADER_SIZE = FB_ALIGN(sizeof(MonitoringHeader), FB_ALIGNMENT);
} // namespace
const Format* MonitoringTableScan::getFormat(thread_db* tdbb, jrd_rel* relation) const
@ -171,7 +174,7 @@ MonitoringData::~MonitoringData()
try
{
if (m_sharedMemory->getHeader() &&
m_sharedMemory->getHeader()->used == alignOffset(sizeof(Header)))
m_sharedMemory->getHeader()->used == HEADER_SIZE)
{
m_sharedMemory->removeMapFile();
}
@ -212,7 +215,7 @@ void MonitoringData::acquire()
while (m_sharedMemory->getHeader()->isDeleted())
{
// Shared memory must be empty at this point
fb_assert(m_sharedMemory->getHeader()->used == alignOffset(sizeof(Header)));
fb_assert(m_sharedMemory->getHeader()->used == HEADER_SIZE);
m_sharedMemory->mutexUnlock();
m_sharedMemory.reset();
@ -254,11 +257,11 @@ void MonitoringData::enumerate(const char* userName, ULONG generation, SessionLi
// When initializing, collect all sessions older than the given generation.
// Otherwise, remove sessions that have updated their generation.
for (ULONG offset = alignOffset(sizeof(Header)); offset < m_sharedMemory->getHeader()->used;)
for (ULONG offset = HEADER_SIZE; offset < m_sharedMemory->getHeader()->used;)
{
const auto ptr = (UCHAR*) m_sharedMemory->getHeader() + offset;
const auto element = (Element*) ptr;
const ULONG length = alignOffset(sizeof(Element) + element->length);
const ULONG length = element->getBlockLength();
if (!userName || !strcmp(element->userName, userName)) // permitted
{
@ -282,11 +285,11 @@ void MonitoringData::read(const char* userName, TempSpace& temp)
// Copy data of all permitted sessions
for (ULONG offset = alignOffset(sizeof(Header)); offset < m_sharedMemory->getHeader()->used;)
for (ULONG offset = HEADER_SIZE; offset < m_sharedMemory->getHeader()->used;)
{
const auto ptr = (UCHAR*) m_sharedMemory->getHeader() + offset;
const auto element = (Element*) ptr;
const ULONG length = alignOffset(sizeof(Element) + element->length);
const ULONG length = element->getBlockLength();
if (!userName || !strcmp(element->userName, userName)) // permitted
{
@ -301,7 +304,7 @@ void MonitoringData::read(const char* userName, TempSpace& temp)
ULONG MonitoringData::setup(AttNumber att_id, const char* userName, ULONG generation)
{
const ULONG offset = alignOffset(m_sharedMemory->getHeader()->used);
const FB_UINT64 offset = FB_ALIGN(m_sharedMemory->getHeader()->used, FB_ALIGNMENT);
const ULONG delta = offset + sizeof(Element) - m_sharedMemory->getHeader()->used;
ensureSpace(delta);
@ -337,11 +340,11 @@ void MonitoringData::cleanup(AttNumber att_id)
{
// Remove information about the given session
for (ULONG offset = alignOffset(sizeof(Header)); offset < m_sharedMemory->getHeader()->used;)
for (ULONG offset = HEADER_SIZE; offset < m_sharedMemory->getHeader()->used;)
{
const auto ptr = (UCHAR*) m_sharedMemory->getHeader() + offset;
const auto element = (Element*) ptr;
const ULONG length = alignOffset(sizeof(Element) + element->length);
const ULONG length = element->getBlockLength();
if (element->attId == att_id)
{
@ -365,15 +368,23 @@ void MonitoringData::cleanup(AttNumber att_id)
void MonitoringData::ensureSpace(ULONG length)
{
ULONG newSize = m_sharedMemory->getHeader()->used + length;
FB_UINT64 newSize = m_sharedMemory->getHeader()->used + length;
if (newSize > m_sharedMemory->getHeader()->allocated)
{
newSize = FB_ALIGN(newSize, DEFAULT_SIZE);
if (newSize > MAX_ULONG)
{
(Arg::Gds(isc_montabexh) <<
Arg::Gds(isc_random) << Arg::Str("storage size exceeds limit")).raise();
}
FB_UINT64 remapSize = FB_ALIGN(newSize, DEFAULT_SIZE);
if (remapSize > MAX_ULONG)
remapSize = newSize;
#ifdef HAVE_OBJECT_MAP
FbLocalStatus statusVector;
if (!m_sharedMemory->remapFile(&statusVector, newSize, true))
if (!m_sharedMemory->remapFile(&statusVector, (ULONG) remapSize, true))
{
status_exception::raise(&statusVector);
}
@ -402,7 +413,7 @@ bool MonitoringData::initialize(SharedMemoryBase* sm, bool initialize)
// Initialize the shared data header
initHeader(header);
header->used = alignOffset(sizeof(Header));
header->used = HEADER_SIZE;
header->allocated = sm->sh_mem_length_mapped;
}
@ -410,12 +421,6 @@ bool MonitoringData::initialize(SharedMemoryBase* sm, bool initialize)
}
ULONG MonitoringData::alignOffset(ULONG unaligned)
{
return (ULONG) Firebird::MEM_ALIGN(unaligned);
}
// MonitoringSnapshot class

View File

@ -257,9 +257,12 @@ class MonitoringData final : public Firebird::PermanentStorage, public Firebird:
TEXT userName[USERNAME_LENGTH + 1];
ULONG generation;
ULONG length;
};
static ULONG alignOffset(ULONG absoluteOffset);
inline ULONG getBlockLength() const
{
return FB_ALIGN(sizeof(Element) + length, FB_ALIGNMENT);
}
};
public:
class Guard