Skip to content

Commit 11a1156

Browse files
authored
Merge pull request #8896 from FirebirdSQL/work/gh-8885
Fixed bug #8885 : AV when lock manager settings is misconfigured.
2 parents c79b833 + dfd3d09 commit 11a1156

5 files changed

Lines changed: 96 additions & 51 deletions

File tree

src/common/isc_s_proto.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,9 @@ class SharedMemoryBase
279279
int eventWait(event_t* event, const SLONG value, const SLONG micro_seconds);
280280
int eventPost(event_t* event);
281281

282+
// Used as memory allocation unit and mapping alignment
283+
static ULONG getSystemPageSize(Firebird::CheckStatusWrapper* status);
284+
282285
public:
283286
#ifdef UNIX
284287
Firebird::AutoPtr<FileLock> mainLock;
@@ -296,6 +299,7 @@ class SharedMemoryBase
296299
#endif
297300

298301
ULONG sh_mem_length_mapped;
302+
ULONG sh_mem_increment; // Suggested growth increment
299303
#ifdef WIN_NT
300304
HANDLE sh_mem_handle; // file handle
301305
HANDLE sh_mem_object; // file mapping

src/common/isc_sync.cpp

Lines changed: 68 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,12 +1250,38 @@ void SharedMemoryBase::internalUnmap()
12501250
}
12511251
}
12521252

1253+
1254+
ULONG SharedMemoryBase::getSystemPageSize(CheckStatusWrapper* statusVector)
1255+
{
1256+
// Get system page size as this is the unit of mapping.
1257+
1258+
#ifdef SOLARIS
1259+
const long ps = sysconf(_SC_PAGESIZE);
1260+
if (ps == -1)
1261+
{
1262+
error(statusVector, "sysconf", errno);
1263+
return 0;
1264+
}
1265+
#else
1266+
const int ps = getpagesize();
1267+
if (ps == -1)
1268+
{
1269+
error(statusVector, "getpagesize", errno);
1270+
return 0;
1271+
}
1272+
#endif
1273+
return ps;
1274+
}
1275+
1276+
12531277
SharedMemoryBase::SharedMemoryBase(const TEXT* filename, ULONG length, IpcObject* callback, bool skipLock)
12541278
:
12551279
#ifdef HAVE_SHARED_MUTEX_SECTION
12561280
sh_mem_mutex(0),
12571281
#endif
1258-
sh_mem_length_mapped(0), sh_mem_header(NULL),
1282+
sh_mem_length_mapped(0),
1283+
sh_mem_increment(0),
1284+
sh_mem_header(NULL),
12591285
sh_mem_callback(callback)
12601286
{
12611287
/**************************************
@@ -1286,6 +1312,14 @@ SharedMemoryBase::SharedMemoryBase(const TEXT* filename, ULONG length, IpcObject
12861312
TEXT init_filename[MAXPATHLEN];
12871313
iscPrefixLock(init_filename, INIT_FILE, true);
12881314

1315+
if (length)
1316+
{
1317+
sh_mem_increment = length = FB_ALIGN(length, getSystemPageSize(&statusVector));
1318+
1319+
if (statusVector.hasData())
1320+
status_exception::raise(&statusVector);
1321+
}
1322+
12891323
const bool trunc_flag = (length != 0);
12901324

12911325
// open the init lock file
@@ -1569,8 +1603,17 @@ void SharedMemoryBase::internalUnmap()
15691603
unlinkFile();
15701604
}
15711605

1606+
1607+
ULONG SharedMemoryBase::getSystemPageSize(CheckStatusWrapper* /*statusVector*/)
1608+
{
1609+
SYSTEM_INFO sys_info;
1610+
GetSystemInfo(&sys_info);
1611+
return sys_info.dwAllocationGranularity;
1612+
}
1613+
1614+
15721615
SharedMemoryBase::SharedMemoryBase(const TEXT* filename, ULONG length, IpcObject* cb, bool /*skipLock*/)
1573-
: sh_mem_mutex(0), sh_mem_length_mapped(0),
1616+
: sh_mem_mutex(0), sh_mem_length_mapped(0), sh_mem_increment(0),
15741617
sh_mem_handle(INVALID_HANDLE_VALUE), sh_mem_object(0), sh_mem_interest(0), sh_mem_hdr_object(0),
15751618
sh_mem_hdr_address(0), sh_mem_header(NULL), sh_mem_callback(cb), sh_mem_unlink(false)
15761619
{
@@ -1598,6 +1641,17 @@ SharedMemoryBase::SharedMemoryBase(const TEXT* filename, ULONG length, IpcObject
15981641
bool init_flag = false;
15991642
DWORD err = 0;
16001643

1644+
if (length)
1645+
{
1646+
LocalStatus ls;
1647+
CheckStatusWrapper statusVector(&ls);
1648+
1649+
sh_mem_increment = length = FB_ALIGN(length, getSystemPageSize(&statusVector));
1650+
1651+
if (statusVector.hasData())
1652+
status_exception::raise(&statusVector);
1653+
}
1654+
16011655
// retry to attach to mmapped file if the process initializing dies during initialization.
16021656

16031657
retry:
@@ -1925,24 +1979,9 @@ UCHAR* SharedMemoryBase::mapObject(CheckStatusWrapper* statusVector, ULONG objec
19251979
*
19261980
**************************************/
19271981

1928-
// Get system page size as this is the unit of mapping.
1929-
1930-
#ifdef SOLARIS
1931-
const long ps = sysconf(_SC_PAGESIZE);
1932-
if (ps == -1)
1933-
{
1934-
error(statusVector, "sysconf", errno);
1982+
const ULONG page_size = getSystemPageSize(statusVector);
1983+
if (!page_size)
19351984
return NULL;
1936-
}
1937-
#else
1938-
const int ps = getpagesize();
1939-
if (ps == -1)
1940-
{
1941-
error(statusVector, "getpagesize", errno);
1942-
return NULL;
1943-
}
1944-
#endif
1945-
const ULONG page_size = (ULONG) ps;
19461985

19471986
// Compute the start and end page-aligned offsets which contain the object being mapped.
19481987

@@ -1980,24 +2019,9 @@ void SharedMemoryBase::unmapObject(CheckStatusWrapper* statusVector, UCHAR** obj
19802019
* Zero the object pointer after a successful unmap.
19812020
*
19822021
**************************************/
1983-
// Get system page size as this is the unit of mapping.
1984-
1985-
#ifdef SOLARIS
1986-
const long ps = sysconf(_SC_PAGESIZE);
1987-
if (ps == -1)
1988-
{
1989-
error(statusVector, "sysconf", errno);
1990-
return;
1991-
}
1992-
#else
1993-
const int ps = getpagesize();
1994-
if (ps == -1)
1995-
{
1996-
error(statusVector, "getpagesize", errno);
2022+
const size_t page_size = getSystemPageSize(statusVector);
2023+
if (!page_size)
19972024
return;
1998-
}
1999-
#endif
2000-
const size_t page_size = (ULONG) ps;
20012025

20022026
// Compute the start and end page-aligned addresses which contain the mapped object.
20032027

@@ -2035,9 +2059,7 @@ UCHAR* SharedMemoryBase::mapObject(CheckStatusWrapper* statusVector,
20352059
*
20362060
**************************************/
20372061

2038-
SYSTEM_INFO sys_info;
2039-
GetSystemInfo(&sys_info);
2040-
const ULONG page_size = sys_info.dwAllocationGranularity;
2062+
const ULONG page_size = getSystemPageSize(statusVector);
20412063

20422064
// Compute the start and end page-aligned offsets which
20432065
// contain the object being mapped.
@@ -2047,6 +2069,8 @@ UCHAR* SharedMemoryBase::mapObject(CheckStatusWrapper* statusVector,
20472069
const ULONG length = end - start;
20482070
const HANDLE handle = sh_mem_object;
20492071

2072+
fb_assert(end <= sh_mem_length_mapped);
2073+
20502074
UCHAR* address = (UCHAR*) MapViewOfFile(handle, FILE_MAP_WRITE, 0, start, length);
20512075

20522076
if (address == NULL)
@@ -2075,9 +2099,7 @@ void SharedMemoryBase::unmapObject(CheckStatusWrapper* statusVector,
20752099
* Zero the object pointer after a successful unmap.
20762100
*
20772101
**************************************/
2078-
SYSTEM_INFO sys_info;
2079-
GetSystemInfo(&sys_info);
2080-
const size_t page_size = sys_info.dwAllocationGranularity;
2102+
const size_t page_size = getSystemPageSize(statusVector);
20812103

20822104
// Compute the start and end page-aligned offsets which
20832105
// contain the object being mapped.
@@ -2497,6 +2519,8 @@ bool SharedMemoryBase::remapFile(CheckStatusWrapper* statusVector, ULONG new_len
24972519

24982520
if (flag)
24992521
{
2522+
new_length = FB_ALIGN(new_length, getSystemPageSize(statusVector));
2523+
25002524
FB_UNUSED(os_utils::ftruncate(mainLock->getFd(), new_length));
25012525

25022526
if (new_length > sh_mem_length_mapped)
@@ -2553,6 +2577,8 @@ bool SharedMemoryBase::remapFile(CheckStatusWrapper* statusVector,
25532577

25542578
if (flag)
25552579
{
2580+
new_length = FB_ALIGN(new_length, getSystemPageSize(statusVector));
2581+
25562582
LARGE_INTEGER offset;
25572583
offset.QuadPart = new_length;
25582584

src/jrd/event.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,8 +534,10 @@ frb* EventManager::alloc_global(UCHAR type, ULONG length, bool recurse)
534534
#ifdef HAVE_OBJECT_MAP
535535
if (!best && !recurse)
536536
{
537+
fb_assert(length <= m_sharedMemory->sh_mem_increment);
538+
537539
const ULONG old_length = m_sharedMemory->sh_mem_length_mapped;
538-
const ULONG ev_length = old_length + m_config->getEventMemSize();
540+
const ULONG ev_length = old_length + m_sharedMemory->sh_mem_increment;
539541

540542
LocalStatus ls;
541543
CheckStatusWrapper localStatus(&ls);

src/lock/lock.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,26 @@ LockManager::LockManager(const string& id, const Config* conf)
177177
m_config(conf),
178178
m_acquireSpins(m_config->getLockAcquireSpins()),
179179
m_memorySize(m_config->getLockMemSize()),
180+
m_hashSlots(m_config->getLockHashSlots()),
180181
m_useBlockingThread(m_config->getServerMode() != MODE_SUPER)
181182
#ifdef USE_SHMEM_EXT
182183
, m_extents(getPool())
183184
#endif
184185
{
186+
if (m_hashSlots < HASH_MIN_SLOTS)
187+
m_hashSlots = HASH_MIN_SLOTS;
188+
if (m_hashSlots > HASH_MAX_SLOTS)
189+
m_hashSlots = HASH_MAX_SLOTS;
190+
191+
// memory size required to fit all hash slots, history blocks and header blocks
192+
const auto minMemory = sizeof(lhb) +
193+
FB_ALIGN(sizeof(shb), FB_ALIGNMENT) +
194+
sizeof(lhb::lhb_hash[0]) * m_hashSlots +
195+
FB_ALIGN(sizeof(his), FB_ALIGNMENT) * HISTORY_BLOCKS * 2;
196+
197+
if (m_memorySize < minMemory)
198+
m_memorySize = minMemory;
199+
185200
LocalStatus ls;
186201
CheckStatusWrapper localStatus(&ls);
187202
if (!init_shared_file(&localStatus))
@@ -304,6 +319,9 @@ bool LockManager::init_shared_file(CheckStatusWrapper* statusVector)
304319

305320
const auto header = tmp->getHeader();
306321
checkHeader(header);
322+
323+
// Get properly aligned value
324+
m_memorySize = m_sharedMemory->sh_mem_increment;
307325
}
308326
catch (const Exception& ex)
309327
{
@@ -2330,13 +2348,7 @@ bool LockManager::initialize(SharedMemoryBase* sm, bool initializeMemory)
23302348
SRQ_INIT(hdr->lhb_free_locks);
23312349
SRQ_INIT(hdr->lhb_free_requests);
23322350

2333-
int hash_slots = m_config->getLockHashSlots();
2334-
if (hash_slots < HASH_MIN_SLOTS)
2335-
hash_slots = HASH_MIN_SLOTS;
2336-
if (hash_slots > HASH_MAX_SLOTS)
2337-
hash_slots = HASH_MAX_SLOTS;
2338-
2339-
hdr->lhb_hash_slots = (USHORT) hash_slots;
2351+
hdr->lhb_hash_slots = m_hashSlots;
23402352
hdr->lhb_scan_interval = m_config->getDeadlockTimeout();
23412353
hdr->lhb_acquire_spins = m_acquireSpins;
23422354

src/lock/lock_proto.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,8 @@ class LockManager final : public Firebird::GlobalStorage, public Firebird::IpcOb
507507

508508
// configurations parameters - cached values
509509
const ULONG m_acquireSpins;
510-
const ULONG m_memorySize;
510+
ULONG m_memorySize;
511+
USHORT m_hashSlots;
511512
const bool m_useBlockingThread;
512513

513514
#ifdef USE_SHMEM_EXT

0 commit comments

Comments
 (0)