Commit 51069adaef1 for php

commit 51069adaef1a6abe06b09fe1fa69837bfb45bfa0
Author: Piotr Hałas <piotr@halas.net.pl>
Date:   Tue Oct 6 10:42:19 2026 +0200

    ext/opcache: drop the pre-emptive munmap before the huge page remap (#23574)

    create_segments() reserved requested_size + huge_page_size, unmapped the
    whole reservation, and only then MAP_FIXED-mapped the huge pages at the
    aligned address inside it.

    That munmap is unnecessary: MAP_FIXED replaces the overlapped part of the
    reservation atomically. It also opens a window in which another thread can
    map something at that address before the remap runs.

    Keep the reservation, map the huge pages into it, and release only the head
    and the tail that are left over. Their sizes always add up to exactly
    huge_page_size, because the reservation is requested_size + huge_page_size
    and the mapping is requested_size.

    When the remap fails the whole reservation is released before falling back
    to normal pages: the kernel may already have discarded the overlapped part,
    so the reservation cannot be reused.

diff --git a/ext/opcache/shared_alloc_mmap.c b/ext/opcache/shared_alloc_mmap.c
index 4825da3e4c0..b7ef52ac5d6 100644
--- a/ext/opcache/shared_alloc_mmap.c
+++ b/ext/opcache/shared_alloc_mmap.c
@@ -245,12 +245,18 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_

 		p = mmap(NULL, requested_size + huge_page_size, flags, MAP_SHARED|MAP_ANONYMOUS|MAP_32BIT, fd, 0);
 		if (p != MAP_FAILED) {
-			munmap(p, requested_size + huge_page_size);
+			void *reserved = p;
 			p = (void*)(ZEND_MM_ALIGNED_SIZE_EX((ptrdiff_t)p, huge_page_size));
 			p = mmap(p, requested_size, flags, MAP_SHARED|MAP_ANONYMOUS|MAP_32BIT|MAP_HUGETLB|MAP_FIXED, -1, 0);
 			if (p != MAP_FAILED) {
+				size_t head = (char*)p - (char*)reserved;
+				if (head != 0) {
+					munmap(reserved, head);
+				}
+				munmap((char*)p + requested_size, huge_page_size - head);
 				goto success;
 			} else {
+				munmap(reserved, requested_size + huge_page_size);
 				p = mmap(NULL, requested_size, flags, MAP_SHARED|MAP_ANONYMOUS|MAP_32BIT, fd, 0);
 				if (p != MAP_FAILED) {
 					goto success;