View Issue Details
|ID||Project||Category||View Status||Date Submitted||Last Update|
|0004767||CentOS-5||glib||public||2011-03-16 17:48||2011-03-19 21:58|
|Target Version||Fixed in Version|
|Summary||0004767: MAP_GROWSDOWN cause SIGBUS errors after upgrading to Centos 5.5|
|Description||I was upgrading the OS on one of our build from Centos 5.3 32bit to Centos 5.5 32bit. After doing the package update I rebooted, checked out a clean copy of the source, built and ran the unit tests. All unit tests which rely on our MemMap base class began to fail.|
The crash occurs when we attempt to set the value of the guard page after immediatly after mapping the memory. After poking around I was able to isolate the problem to our use of the MAP_GROWSDOWN flag, the tests run fine without it but crash when the flag is set. These tests worked fine when the build system was running 5.3, but immediately started crashing when we upgraded to 5.5. This is a stable bit of code which hasn't been modified in several releases and has unit test coverage north of 80%. This has been reproduced on multiple machines, some of which are XEN VMs and some are real hardware.
int flags = MAP_ANONYMOUS|MAP_PRIVATE|MAP_GROWSDOWN;
int prot = PROT_EXEC|PROT_READ|PROT_WRITE;
size_t length = 524288;
long rv = ::sysconf(_SC_PAGESIZE);
if (rv < 0)
size_t pagelength = size_t(rv);
// Adjust length for guard page
length = pagelength * (((length + pagelength - 1) / pagelength) + 1);
m_addr = ::mmap(NULL, length, prot, flags, -1, 0);
if (m_addr == MAP_FAILED)
m_stackaddr = static_cast<void *>(static_cast<char *>(m_addr) + pagelength);
m_length = length - pagelength;
// Fill the guard page with an interesting pattern
unsigned int *g = static_cast<unsigned int *>(m_addr);
for (size_t i=0; i < pagelength; i += sizeof(unsigned int))
*g++ = 0xBADC0FFEU; <-- SIGBUS HAPPENS HERE ON FIRST ITERATION
|Tags||No tags attached.|
|One of our engineers was able to pare down the example to a very small test program which reproduced the issue. I've attached it as mmap_demo.cpp|
mmap_demo.cpp (712 bytes)
g++ mmap_demo.cpp ; ./a.out
* Returned memory is all usable
* If you mmap 1 page, it is always usable
* If you mmap 128+ pages, the first page is unusable with 10% probabaility unless the previous ~20 requests were usable, in which case the first page is usable with approximately 100% probability.
* As you increase the size of the allocation from 8 pages towards 1000, the probability of the first page in the result being usable steadily decreases.
* The second page in the result is always usable.
* If the first page isn't writeable, it wasn't readable either.
* If I use CentOS 5.3 in a VM, it just works. If I use CentOS 5.5 on real hardware, it fails.
|http://lwn.net/Articles/294001/ ? maybe it was removed between 5.3 and 5.5|
|2011-03-16 17:48||mstump||New Issue|
|2011-03-17 20:52||mstump||Note Added: 0012522|
|2011-03-17 20:52||mstump||File Added: mmap_demo.cpp|
|2011-03-17 20:53||mstump||Note Added: 0012523|
|2011-03-19 21:45||tru||Note Added: 0012528|
|2011-03-19 21:57||tru||Note Added: 0012529|
|2011-03-19 21:58||tru||Note Added: 0012530|