Bug 24551 - mmap: accessing memory beyond mmap-ed region doesn't segfault
Summary: mmap: accessing memory beyond mmap-ed region doesn't segfault
Status: RESOLVED INVALID
Alias: None
Product: glibc
Classification: Unclassified
Component: malloc (show other bugs)
Version: 2.29
: P2 minor
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-05-14 00:36 UTC by jRy3TfXGGm3
Modified: 2019-05-14 06:58 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description jRy3TfXGGm3 2019-05-14 00:36:42 UTC
Is this even a bug?

with glibc 2.28 mmap-ing 1 byte (in a kernel with page_size 4096 bytes) like:
`addr = mmap (NULL, size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);`
... allows accesses until addr[16384-1] and only segfaults at accessing addr[16384] (page 4 instead of 2)

but with glibc 2.29, segfault happens only at addr[188416]  (page 46 instead of 2)

for details see comment 14 & 15 in: https://bugzilla.kernel.org/show_bug.cgi?id=203537#c14


Note that I tried this with MAP_FILE (and an actual file) not just with MAP_ANONYMOUS but I found that the effects/results are the same.

I would expect segfault(or SIGBUSS? according to the man page) would happen when hitting page 2 (ie. addr[0x1000]) but this would seem to require something like what valdis mentioned: " * valdis wonders how hard it would be to add an "allocate non-accessible guard page at both ends" flag to mmap()."

So, is the manual in need of updating? since SIGBUS isn't generated as stated in these circumstances:

man 2 mmap:
    SIGBUS Attempted access to a portion of the buffer that does not correspond to the file (for example, beyond the end of the file, including the case where another process has truncated the file).

man mmap (ie. map 3p mmap):
    The system shall always zero-fill any partial page at the end of an object. Further, the system shall never write out any modified portions of the last page of an object which are beyond its end. References within the address range starting at pa and continuing for len bytes to whole pages following the end of an object shall result in delivery of a SIGBUS signal.
    An implementation may generate SIGBUS signals when a reference would cause an error in the mapped object, such as out-of-space condition.

(pa=addr and len=size in my case)

At the very least, SIGBUS isn't generated beyond the end of the file until the end of the page.

Note: SIGBUS is generated when file is a 0 byte file (from what I've tested) and this is to be expected and working normally (now that I know enough to understand it).

For a 200MiB mmap, both glibc versions allow accesses until page 442 beyond mmap-ed region is reached (page 443 for v2.29) and only then segfault.
Comment 1 jRy3TfXGGm3 2019-05-14 00:39:49 UTC
oops
What not to put in a new report:
 Questions about the correctness or the expected behaviour of standardised system calls. These might be more appropriately asked in other forums.
Comment 2 Florian Weimer 2019-05-14 06:58:35 UTC
If you need guard pages, you need to map extra pages and leave them with PROT_NONE protection flags.

Changes in mapping behavior are expected for different kernel versions.  Different glibc versions have different library sizes and perhaps even load segments, so they trigger different kernel behavior, too.