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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.