View Issue Details

IDProjectCategoryView StatusLast Update
0004767CentOS-5glibpublic2011-03-19 21:58
Reportermstump 
PrioritynormalSeverityminorReproducibilitysometimes
Status newResolutionopen 
Product Version5.5 
Target VersionFixed in Version 
Summary0004767: MAP_GROWSDOWN cause SIGBUS errors after upgrading to Centos 5.5
DescriptionI 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)
    throw SystemException(errno);
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)
    throw SystemException(errno);

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
TagsNo tags attached.

Activities

mstump

mstump

2011-03-17 20:52

reporter   ~0012522

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

2011-03-17 20:52

 

mmap_demo.cpp (712 bytes)
mstump

mstump

2011-03-17 20:53

reporter   ~0012523

g++ mmap_demo.cpp ; ./a.out

Results:
Without _GROWSDOWN:
* Returned memory is all usable

With _GROWSDOWN:
* 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.
tru

tru

2011-03-19 21:45

administrator   ~0012528

http://lwn.net/Articles/294001/ ? maybe it was removed between 5.3 and 5.5
tru

tru

2011-03-19 21:57

administrator   ~0012529

http://mail.gnome.org/archives/gtk-vnc-list/2007-September/msg00024.html
tru

tru

2011-03-19 21:58

administrator   ~0012530

http://clozure.com/pipermail/openmcl-devel/2010-November/012323.html

Issue History

Date Modified Username Field Change
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