Bug 169608 - [libc] the mmap(), mprotect(), and munmap() functions get screwed by some corner-case arguments
Summary: [libc] the mmap(), mprotect(), and munmap() functions get screwed by some cor...
Status: Open
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: Unspecified
Hardware: Any Any
: Normal Affects Only Me
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-07-02 19:30 UTC by deeptech71@gmail.com
Modified: 2019-03-30 14:48 UTC (History)
3 users (show)

See Also:


Attachments
xs.c (1.62 KB, text/plain; charset=UTF-8)
2012-07-02 19:42 UTC, deeptech71@gmail.com
no flags Details
r.sh (367 bytes, text/plain; charset=UTF-8)
2012-07-02 19:44 UTC, deeptech71@gmail.com
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description deeptech71@gmail.com 2012-07-02 19:30:09 UTC
As it turns out, the mmap(), mprotect(), and munmap() functions behave
very badly when they are handed some corner-case arguments. Their behavior
is also inconsistent with the descriptions in the man pages. Not to mention
that, as I'd say, the man pages are very poor (which is definitely true
compared to Linux's man pages).

See the (to be) attached test program, execution script, and sample
output; these are for/on 32-bit machines. The WRONGly looking pieces
of output are:

* [6/30] mmap(0x0, 4294967295, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0)... success: got 0x28049000; writing here... Segmentation fault (core dumped)
  mmap() returns a "successful" pointer, but the area is not writable. Also see cases [12/30], [18/30], and [24/30] for mmap().
* [14/30] mmap(0xdeadbeef, 4096, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0)... Cannot allocate memory
  A hint (a non-NULL first argument) should not interfere with mmap()'s ability to succeed in allocating memory. Also see cases [15/30], [20/30], and [21/30] for mmap().
* [30/30] mmap(0xffffffff, 4294967295, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0)... No such file or directory
  WTF?!
* [6/30] mprotect(0x0, 4294967295, PROT_NONE)... success!
  Did mprotect() really restrict ~4GiB of memory? Also see cases [11/30], [12/30], [17/30], [18/30], [24/30], and [29/30] for mprotect(). Notably, 0xfffff000 seems to play along with 4294967295, but not 4294963200; while 0xffffffff seems to play along with 4294963200, but not 4294967295.
* [8/30] munmap(0xbeef, 4096)... success!
  0xBEEF is not page-aligned, but the man page says that it should be. Also, see many other cases for munmap().
* [11/30] munmap(0xbeef, 4294963200)... success!
  Did munmap() really unmap ~4GiB of memory? Also see case [12/30] for munmap().

As a comparison, the output on a (64-bit) Linux machine suggests that
Linux's relevant functions are more robust. 

BTW: The man page for munmap() says that the function will set errno to
EINVAL if "The addr argument was not page aligned, the len argument was
zero or negative, or some part of the region being unmapped is outside
the valid address range for a process.". Negative size_t? You've gotta
be kidding me!

How-To-Repeat: Compile xs.c (to a.out), and then run the r.sh script. (These files are
to be attached.)
Comment 1 Eitan Adler freebsd_committer freebsd_triage 2017-12-31 07:59:04 UTC
For bugs matching the following criteria:

Status: In Progress Changed: (is less than) 2014-06-01

Reset to default assignee and clear in-progress tags.

Mail being skipped
Comment 2 Glenn Weinberg 2018-09-19 17:18:22 UTC
munmap() not failing misaligned addresses as documented breaks PMDK.
Comment 3 Konstantin Belousov freebsd_committer freebsd_triage 2019-03-30 14:48:23 UTC
(In reply to Glenn Weinberg from comment #2)
What happens is (all arithmetic is done using unsigned native register size):
- we truncate the base address down to the page boundary
- size is increased by the truncated amount
- size is rounded up to the page boundary
- if base + size < base, we decline
- base is set to max(min user address, base)
- end is set to min(max user address, base + size)
- base > end, base = end

I think that corner cases of this algorithm are put in stone after 30 years of FreeBSD history.  In particular, I do not think we can remove the automatic realignment.