Anonymous mmap zero-filled?
It's hard to say which ones promise what without simply exhaustively enumerating all man pages or other release documentation, but the underlying code that handles MAP_ANON
is (usually? always?) also used to map in bss space for executables, and bss space needs to be zero-filled. So it's pretty darn likely.
As for "giving you back your old values" (or some non-zero values but most likely, your old ones) if you unmap and re-map, it certainly seems possible, if some system were to be "lazy" about deallocation. I have only used a few systems that support mmap
in the first place (BSD and Linux derivatives) and neither one is lazy that way, at least, not in the kernel code handling mmap
.
The reason sbrk
might or might not zero-fill a "regrown" page is probably tied to history, or lack thereof. The current FreeBSD code matches with what I recall from the old, pre-mmap
days: there are two semi-secret variables, minbrk
and curbrk
, and both brk
and sbrk
will only invoke SYS_break
(the real system call) if they are moving curbrk
to a value that is at least minbrk
. (Actually, this looks slightly broken: brk
has the at-least behavior but sbrk
just adds its argument to curbrk
and invokes SYS_break
. Seems harmless since the kernel checks, in sys_obreak()
in /sys/vm/vm_unix.c
, so a too-negative sbrk()
will fail with EINVAL
.)
I'd have to look at the Linux C library (and then perhaps kernel code too) but it may simply ignore attempts to "lower the break", and merely record a "logical break" value in libc. If you have mmap()
and no backwards compatibility requirements, you can implement brk()
and sbrk()
entirely in libc, using anonymous mappings, and it would be trivial to implement both of them as "grow-only", as it were.
Which flavors of Unix promise to return zero-initialized memory from anonymous mmaps?
GNU/Linux
As you said in your question, the Linux version of mmap promises to zero-fill anonymous mappings:
MAP_ANONYMOUS
The mapping is not backed by any file; its contents are initialized to zero.
NetBSD
The NetBSD version of mmap promises to zero-fill anonymous mappings:
MAP_ANON
Map anonymous memory not associated with any specific file. The file descriptor is not used for creating
MAP_ANON
regions, and must be specified as-1
. The mapped memory will be zero filled.
OpenBSD
The OpenBSD manpage of mmap does not promise to zero-fill anonymous mappings. However, Theo de Raadt (prominent OpenBSD developer), declared in November 2019 on the OpenBSD mailing list:
Of course it is zero filled. What else would it be? There are no plausible alternatives.
I think it detracts from the rest of the message to say something so obvious.
And the other OpenBSD developers did not contradict him.
IBM AIX
The AIX version of mmap promises to zero-fill anonymous mappings:
MAP_ANONYMOUS
Specifies the creation of a new, anonymous memory region that is initialized to all zeros.
HP-UX
According to nixdoc.net, the HP-UX version of mmap promises to zero-fill anonymous mappings:
If
MAP_ANONYMOUS
is set inflags
, a new memory region is created and initialized to all zeros.
Solaris
The Solaris version of mmap promises to zero-fill anonymous mappings:
When
MAP_ANON
is set inflags
, andfildes
is set to -1,mmap()
provides a direct path to return anonymous pages to the caller. This operation is equivalent to passingmmap()
an open file descriptor on/dev/zero
withMAP_ANON
elided from theflags
argument.
This Solaris man page gives us a way to get zero-filled memory pages without relying on the behavior of mmap used with the MAP_ANONYMOUS
flag: do not use the MAP_ANONYMOUS
flag, and create a mapping backed by the /dev/zero
file. It would be useful to know the list of Unix-like operating systems providing the /dev/zero
file, to see if this approach is more portable than using the MAP_ANONYMOUS
flag (neither /dev/zero nor MAP_ANONYMOUS are POSIX).
Interestingly, the Wikipedia article about /dev/zero claims that MAP_ANONYMOUS
was introduced to remove the need of opening /dev/zero
when creating an anonymous mapping.