Re: Is this change in mmap() behavior intentional or a bug?

From: Konstantin Belousov <kostikbel_at_gmail.com>
Date: Wed, 09 Apr 2025 03:09:28 UTC
On Tue, Apr 08, 2025 at 06:37:25PM -0700, Bakul Shah wrote:
> On Apr 8, 2025, at 6:03 PM, Konstantin Belousov <kostikbel@gmail.com> wrote:
> > 
> > On Tue, Apr 08, 2025 at 03:46:27PM -0700, Bakul Shah wrote:
> >> The attached program works on FreeBSD-12.1 but fails on
> >> FreeBSD-14 or later.
> >> 
> >> The idea is to mmap an anon page and then keep writing to every
> >> Nth word until given number of times. Attempts to write beyond
> >> the allocated space will trap and in the signal handler we
> >> allocate one more page.
> > 
> >> Since we are allocating pages to
> >> appear in the virtual address space (and since no other code
> >> allocates space) we should get a continuous range of pages.
> > This is generally not true, the spec never provided such guarantees.
> > If you need the second and subsequent mappings at the specific address,
> > use MAP_FIXED.
> > 
> > The change in the behavior is called ASLR, and some people even claimed
> > that it is for good.
> 
> I believe the intent for the original wording was to cover the case
> when a given address is *not* aligned to a page boundary, not for ASLR
> (which didn't raise its head until much later). IMHO if a page aligned
> address is given mmap() should *strive* to provide just that. ASLR
> should apply only when the given address is 0.
This is your belief.

> 
> MAP_FIXED has some additional semantics such as replacing any previous
> mapping, which can create its own confusing behavior. Now one has to
> add MAP_EXCL as well I suppose. Still, at least there is a work around.
Yes, MAP_EXCL was added to match the semantic of MAP_FIXED to non-fixed
mapping.

> 
> Thanks for your response.
> 
> Bakul
> 
> > 
> >> 
> >> Usage: a.out [-v] count [incr [val [addr]]]
> >> 
> >> On 12.1:
> >> $ ./a.out -v 4 0x800
> >> count=4, val=0x12345678, addr=0x100000, incr=0x800
> >> 0x100000: 12345678
> >> 0x100800: 12345679
> >> 0x101000: 1234567a
> >> 0x101800: 1234567b
> >> 2 allocs
> >> 
> >> On 14.2-stable:
> >> $ ./a.out -v 4 0x800
> >> count=4, val=0x12345678, addr=0x75d000, incr=0x800
> >> 0x75d000: 12345678
> >> 0x75d800: 12345679
> >> mmap: want 0x75e000, got 0x8210ae000
> >> 
> >> Looking at /proc/$pid/map (just after the first mmap) shows
> >> there is a huge gap after the allocated page. Also, each time
> >> this is run, a page is allocated at a different virtual address (unlike on 12.1).
> >> 
> >> This appears like a bug but I thought I'd ask here first.
> >> 
> >> Thanks for any insight!
> >> 
> >> -- bakul
> >> 
> >> PS: added code to pause after the first mmap.
> >> 
> > 
> > 
>