From: Alejandro Colomar <alx@kernel.org>
To: Ben Kallus <benjamin.p.kallus.gr@dartmouth.edu>
Cc: linux-man@vger.kernel.org
Subject: Re: [PATCH] man/man2/mmap.2: Document when MAP_GROWSDOWN does/doesn't trigger growth
Date: Mon, 4 May 2026 15:00:57 +0200 [thread overview]
Message-ID: <afiVz8xRiJ0jQzXZ@devuan> (raw)
In-Reply-To: <20260423164414.1952395-1-benjamin.p.kallus.gr@dartmouth.edu>
[-- Attachment #1: Type: text/plain, Size: 5688 bytes --]
Hi Ben,
On 2026-04-23T12:44:14-0400, Ben Kallus wrote:
> The man page states that MAP_GROWSDOWN can only cause a mapping to
> grow by a single page. This is incorrect; mappings can grow by many
> pages at a time, until reaching either the stack size limit or growing
> too close to another mapping.
>
> To observe that mappings can grow by more than one page, and that they
> are limited by the stack size limit, run the following C program with a
> stack size limit of 0x800000 bytes, and then again with a stack size limit
> of 0x801000 bytes, and observe that it segfaults as the comments describe.
Would you mind pasting a shell session that runs it with both stack
limits?
>
> > struct page {
> > char data[4096];
> > };
> > static_assert(sizeof(struct page) == 4096);
> >
> > void *const BASE_ADDRESS = (void *)0xabcdef000;
I'd prefer upper-casing the hex value, to differentiate it visually
from the 'x':
0xABCDEF000;
If this seems too packed, C23 now allows using a digit separator:
alx@devuan:~/tmp$ cat s.c
void *const BASE_ADDRESS = (void *)0xA'BCDE'F000;
alx@devuan:~/tmp$ gcc -Wall -Wextra -S s.c
alx@devuan:~/tmp$
> >
> > int main(int const argc, char const * const * const argv) {
Unrelated, but you can define int main(void) without parameters. That's
allowed by ISO C. Here's a quote of C23, but this is allowed by any
version of ISO C:
5.1.2.3.2 Program startup
1 The function called at program startup is named main.
The implementation declares no prototype for this function.
It shall be defined with a return type of int
and with no parameters:
int main(void) { /* ... */ }
or with two parameters
(referred to here as argc and argv,
though any names may be used,
as they are local to the function in which they are declared):
int main(int argc, char *argv[]) { /* ... */ }
or equivalent;6)
or in some other implementation-defined manner.
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf#paragraph.5.1.2.3.2>
> > volatile struct page *p = mmap(
> > BASE_ADDRESS,
> > 1,
> > PROT_READ | PROT_WRITE,
> > MAP_ANONYMOUS | MAP_PRIVATE | MAP_GROWSDOWN | MAP_FIXED_NOREPLACE,
> > -1,
> > 0
> > );
> > // stack_limit=0x800000 // stack_limit=0x801000
> > (p - 2047)->data[0] = 0; // no segfault // no segfault
> > (p - 2048)->data[0] = 0; // segfault // no segfault
> > (p - 2049)->data[0] = 0; // segfault // segfault
> > }
>
> To observe that mappings stop growing when they get within 256 pages of
> the next lower mapping (instead of a single page, as the man page
> currently states), run the following program, and observe that it
> segfaults as the comments describe.
Would you mind running the program and pasting that here too?
>
> > struct page {
> > char data[4096];
> > };
> > static_assert(sizeof(struct page) == 4096);
> >
> > struct page *const BASE_ADDRESS = (void *)0xabcdef000;
> >
> > int main(int const argc, char const * const * const argv) {
> > volatile struct page *p = mmap(
> > BASE_ADDRESS,
> > 1,
> > PROT_READ | PROT_WRITE,
> > MAP_ANONYMOUS | MAP_PRIVATE | MAP_GROWSDOWN | MAP_FIXED_NOREPLACE,
> > -1,
> > 0
> > );
> >
> > struct page *p2 = mmap(
> > BASE_ADDRESS - 258,
> > 1,
> > PROT_READ | PROT_WRITE,
> > MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE,
> > -1,
> > 0
> > );
> >
> > // no segfault (causes p to grow by a page)
> > (p - 1)->data[0] = 0;
> >
> > // unmap the test page
> > munmap(p2, 1);
> >
> > // unmap the new page from p growing
> > munmap((struct page *)p - 1, 1);
> >
> > struct page *p3 = mmap(
> > BASE_ADDRESS - 257,
> > 1,
> > PROT_READ | PROT_WRITE,
> > MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE,
> > -1,
> > 0
> > );
> >
> > // segfault because p can't grow due to proximity to p3
> > (p - 1)->data[0] = 0;
> > }
>
> Fixes: 176b1a76 (2016-11-21; "mmap.2: Add (much) more detail on MAP_GROWSDOWN")
> Signed-off-by: Ben Kallus <benjamin.p.kallus.gr@dartmouth.edu>
> ---
> man/man2/mmap.2 | 10 +++++-----
> 1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/man/man2/mmap.2 b/man/man2/mmap.2
> index 20b94c243..925b18ffc 100644
> --- a/man/man2/mmap.2
> +++ b/man/man2/mmap.2
> @@ -276,11 +276,11 @@ should check the returned address against the requested address.
> This flag is used for stacks.
> It indicates to the kernel virtual memory system that the mapping
> should extend downward in memory.
> -Touching an address in the "guard" page below the mapping will cause
> -the mapping to grow by a page.
> -This growth can be repeated until the mapping grows to within a
> -page of the high end of the next lower mapping,
> -at which point touching the "guard" page will result in a
> +Touching an address below the mapping will cause the mapping to grow to
> +accommodate the access.
> +This growth can be repeated until the mapping crosses the stack size limit,
> +or grows to within 256 pages of the high end of the next lower mapping,
> +at which point accessing below the mapping will result in a
Thanks! The diff seems reasonable. Please adjust the commit message
and resend.
Have a lovely day!
Alex
> .B SIGSEGV
> signal.
> .TP
> --
> 2.54.0
>
--
<https://www.alejandro-colomar.es>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
prev parent reply other threads:[~2026-05-04 13:01 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-23 16:44 [PATCH] man/man2/mmap.2: Document when MAP_GROWSDOWN does/doesn't trigger growth Ben Kallus
2026-05-04 13:00 ` Alejandro Colomar [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=afiVz8xRiJ0jQzXZ@devuan \
--to=alx@kernel.org \
--cc=benjamin.p.kallus.gr@dartmouth.edu \
--cc=linux-man@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox