Skip to content

Commit 7cf1a2a

Browse files
committed
Fix SELinux mprotect execheap error due to mem adjacent to heap
It seems SELinux has a bug where memory directly adjacent to the heap is interpreted as heap memory. Dodge this issue by leaving some space between the heap and memory suggested by find_prefered_mmap_base. See GH-12932 See https://bugzilla.kernel.org/show_bug.cgi?id=218258 Closes GH-12942
1 parent 2b8c008 commit 7cf1a2a

File tree

2 files changed

+17
-1
lines changed

2 files changed

+17
-1
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ PHP NEWS
1313
- Opcache:
1414
. Fixed oss-fuzz #64727 (JIT undefined array key warning may overwrite DIM
1515
with NULL when DIM is the same var as result). (ilutov)
16+
. Added workaround for SELinux mprotect execheap issue.
17+
See https://bugzilla.kernel.org/show_bug.cgi?id=218258. (ilutov)
1618

1719
21 Dec 2023, PHP 8.2.14
1820

ext/opcache/shared_alloc_mmap.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,18 @@ static void *find_prefered_mmap_base(size_t requested_size)
6262
}
6363

6464
while (fgets(buffer, MAXPATHLEN, f) && sscanf(buffer, "%lx-%lx", &start, &end) == 2) {
65+
/* Don't place the segment directly before or after the heap segment. Due to an selinux bug,
66+
* a segment directly preceding or following the heap is interpreted as heap memory, which
67+
* will result in an execheap violation for the JIT.
68+
* See https://bugzilla.kernel.org/show_bug.cgi?id=218258. */
69+
bool heap_segment = strstr(buffer, "[heap]") != NULL;
70+
if (heap_segment) {
71+
uintptr_t start_base = start & ~(huge_page_size - 1);
72+
if (last_free_addr + requested_size >= start_base) {
73+
last_free_addr = ZEND_MM_ALIGNED_SIZE_EX(end + huge_page_size, huge_page_size);
74+
continue;
75+
}
76+
}
6577
if ((uintptr_t)execute_ex >= start) {
6678
/* the current segment lays before PHP .text segment or PHP .text segment itself */
6779
if (last_free_addr + requested_size <= start) {
@@ -90,7 +102,9 @@ static void *find_prefered_mmap_base(size_t requested_size)
90102
}
91103
}
92104
last_free_addr = ZEND_MM_ALIGNED_SIZE_EX(end, huge_page_size);
93-
105+
if (heap_segment) {
106+
last_free_addr += huge_page_size;
107+
}
94108
}
95109
fclose(f);
96110
#elif defined(__FreeBSD__)

0 commit comments

Comments
 (0)