Skip to content

Commit c1dd1ee

Browse files
committed
Make some parts of _zend_mm_heap read-only at runtime.
As [presented at OffensiveCon 2024](https://youtu.be/dqKFHjcK9hM?t=1622), having trivially callable writeable function pointers at the top of the heap makes it straightforward to turn a limited write into an arbitrary code execution. Disabling ZEND_MM_HEAP by default isn't doable, as it's used by a couple of profilers, so we're making some parts of `_zend_mm_heap` read-only at runtime instead: this will prevent the custom heap functions pointers from being hijacked, as well as the custom storage ones. We don't put the shadow_key there, since it has a performance impact, and an attacker able to precisely overwrite it is likely already able to read it anyway.
1 parent 37488d6 commit c1dd1ee

File tree

2 files changed

+92
-51
lines changed

2 files changed

+92
-51
lines changed

Zend/zend_alloc.c

Lines changed: 91 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ typedef zend_mm_bitset zend_mm_page_map[ZEND_MM_PAGE_MAP_LEN]; /* 64B */
217217

218218
#define ZEND_MM_BINS 30
219219

220+
#define ZEND_MM_RO_HEAP(heap) ((zend_mm_ro_heap*)((char*)(heap) + zend_mm_get_page_size()))
221+
220222
#if defined(_MSC_VER)
221223
# if UINTPTR_MAX == UINT64_MAX
222224
# define BSWAPPTR(u) _byteswap_uint64(u)
@@ -263,6 +265,21 @@ typedef struct _zend_mm_huge_list zend_mm_huge_list;
263265

264266
static bool zend_mm_use_huge_pages = false;
265267

268+
static size_t zend_mm_get_page_size(void)
269+
{
270+
static size_t page_size = 0;
271+
272+
if (!page_size) {
273+
page_size = zend_get_page_size();
274+
if (!page_size || (page_size & (page_size - 1))) {
275+
/* anyway, we have to return a valid result */
276+
page_size = REAL_PAGE_SIZE;
277+
}
278+
}
279+
280+
return page_size;
281+
}
282+
266283
/*
267284
* Memory is retrieved from OS by chunks of fixed size 2MB.
268285
* Inside chunk it's managed by pages of fixed size 4096B.
@@ -299,9 +316,6 @@ struct _zend_mm_heap {
299316
#if ZEND_MM_CUSTOM
300317
int use_custom_heap;
301318
#endif
302-
#if ZEND_MM_STORAGE
303-
zend_mm_storage *storage;
304-
#endif
305319
#if ZEND_MM_STAT
306320
size_t size; /* current memory usage */
307321
size_t peak; /* peak memory usage */
@@ -329,16 +343,27 @@ struct _zend_mm_heap {
329343
double avg_chunks_count; /* average number of chunks allocated per request */
330344
int last_chunks_delete_boundary; /* number of chunks after last deletion */
331345
int last_chunks_delete_count; /* number of deletion over the last boundary */
346+
#if ZEND_MM_CUSTOM
347+
HashTable *tracked_allocs;
348+
#endif
349+
350+
pid_t pid;
351+
zend_random_bytes_insecure_state rand_state;
352+
};
353+
354+
/* This contains security-sensitive data, and is thus mapped as read-only at run-time right after the _zend_mm_heap struct
355+
* and accessed via the ZEND_MM_RO_HEAP macro.*/
356+
struct _zend_mm_ro_heap {
357+
#if ZEND_MM_STORAGE
358+
zend_mm_storage *storage;
359+
#endif
332360
#if ZEND_MM_CUSTOM
333361
struct {
334362
void *(*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
335363
void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
336364
void *(*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
337365
} custom_heap;
338-
HashTable *tracked_allocs;
339366
#endif
340-
pid_t pid;
341-
zend_random_bytes_insecure_state rand_state;
342367
};
343368

344369
struct _zend_mm_chunk {
@@ -349,7 +374,6 @@ struct _zend_mm_chunk {
349374
uint32_t free_tail; /* number of free pages at the end of chunk */
350375
uint32_t num;
351376
char reserve[64 - (sizeof(void*) * 3 + sizeof(uint32_t) * 3)];
352-
zend_mm_heap heap_slot; /* used only in main chunk */
353377
zend_mm_page_map free_map; /* 512 bits or 64 bytes */
354378
zend_mm_page_info map[ZEND_MM_PAGES]; /* 2 KB = 512 * 4 */
355379
};
@@ -837,8 +861,8 @@ static void *zend_mm_chunk_alloc_int(size_t size, size_t alignment)
837861
static void *zend_mm_chunk_alloc(zend_mm_heap *heap, size_t size, size_t alignment)
838862
{
839863
#if ZEND_MM_STORAGE
840-
if (UNEXPECTED(heap->storage)) {
841-
void *ptr = heap->storage->handlers.chunk_alloc(heap->storage, size, alignment);
864+
if (UNEXPECTED(ZEND_MM_RO_HEAP(heap)->storage)) {
865+
void *ptr = ZEND_MM_RO_HEAP(heap)->storage->handlers.chunk_alloc(ZEND_MM_RO_HEAP(heap)->storage, size, alignment);
842866
ZEND_ASSERT(((uintptr_t)((char*)ptr + (alignment-1)) & (alignment-1)) == (uintptr_t)ptr);
843867
return ptr;
844868
}
@@ -849,8 +873,8 @@ static void *zend_mm_chunk_alloc(zend_mm_heap *heap, size_t size, size_t alignme
849873
static void zend_mm_chunk_free(zend_mm_heap *heap, void *addr, size_t size)
850874
{
851875
#if ZEND_MM_STORAGE
852-
if (UNEXPECTED(heap->storage)) {
853-
heap->storage->handlers.chunk_free(heap->storage, addr, size);
876+
if (UNEXPECTED(ZEND_MM_RO_HEAP(heap)->storage)) {
877+
ZEND_MM_RO_HEAP(heap)->storage->handlers.chunk_free(ZEND_MM_RO_HEAP(heap)->storage, addr, size);
854878
return;
855879
}
856880
#endif
@@ -860,9 +884,9 @@ static void zend_mm_chunk_free(zend_mm_heap *heap, void *addr, size_t size)
860884
static int zend_mm_chunk_truncate(zend_mm_heap *heap, void *addr, size_t old_size, size_t new_size)
861885
{
862886
#if ZEND_MM_STORAGE
863-
if (UNEXPECTED(heap->storage)) {
864-
if (heap->storage->handlers.chunk_truncate) {
865-
return heap->storage->handlers.chunk_truncate(heap->storage, addr, old_size, new_size);
887+
if (UNEXPECTED(ZEND_MM_RO_HEAP(heap)->storage)) {
888+
if (ZEND_MM_RO_HEAP(heap)->storage->handlers.chunk_truncate) {
889+
return ZEND_MM_RO_HEAP(heap)->storage->handlers.chunk_truncate(ZEND_MM_RO_HEAP(heap)->storage, addr, old_size, new_size);
866890
} else {
867891
return 0;
868892
}
@@ -879,9 +903,9 @@ static int zend_mm_chunk_truncate(zend_mm_heap *heap, void *addr, size_t old_siz
879903
static int zend_mm_chunk_extend(zend_mm_heap *heap, void *addr, size_t old_size, size_t new_size)
880904
{
881905
#if ZEND_MM_STORAGE
882-
if (UNEXPECTED(heap->storage)) {
883-
if (heap->storage->handlers.chunk_extend) {
884-
return heap->storage->handlers.chunk_extend(heap->storage, addr, old_size, new_size);
906+
if (UNEXPECTED(ZEND_MM_RO_HEAP(heap)->storage)) {
907+
if (ZEND_MM_RO_HEAP(heap)->storage->handlers.chunk_extend) {
908+
return ZEND_MM_RO_HEAP(heap)->storage->handlers.chunk_extend(ZEND_MM_RO_HEAP(heap)->storage, addr, old_size, new_size);
885909
} else {
886910
return 0;
887911
}
@@ -2045,7 +2069,7 @@ static void zend_mm_free_huge(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZE
20452069

20462070
static void zend_mm_refresh_key(zend_mm_heap *heap)
20472071
{
2048-
zend_random_bytes_insecure(&heap->rand_state, &heap->shadow_key, sizeof(heap->shadow_key));
2072+
zend_random_bytes_insecure(&heap->rand_state, &(heap->shadow_key), sizeof(heap->shadow_key));
20492073
}
20502074

20512075
static void zend_mm_init_key(zend_mm_heap *heap)
@@ -2056,16 +2080,22 @@ static void zend_mm_init_key(zend_mm_heap *heap)
20562080

20572081
static zend_mm_heap *zend_mm_init(void)
20582082
{
2083+
zend_mm_heap *heap = (zend_mm_heap*)zend_mm_chunk_alloc_int(zend_mm_get_page_size() * 2, zend_mm_get_page_size());
2084+
if (UNEXPECTED(heap == NULL)) {
2085+
#if ZEND_MM_ERROR
2086+
fprintf(stderr, "Can't initialize heap\n");
2087+
#endif
2088+
return NULL;
2089+
}
2090+
20592091
zend_mm_chunk *chunk = (zend_mm_chunk*)zend_mm_chunk_alloc_int(ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE);
2060-
zend_mm_heap *heap;
20612092

20622093
if (UNEXPECTED(chunk == NULL)) {
20632094
#if ZEND_MM_ERROR
20642095
fprintf(stderr, "Can't initialize heap\n");
20652096
#endif
20662097
return NULL;
20672098
}
2068-
heap = &chunk->heap_slot;
20692099
chunk->heap = heap;
20702100
chunk->next = chunk;
20712101
chunk->prev = chunk;
@@ -2099,10 +2129,13 @@ static zend_mm_heap *zend_mm_init(void)
20992129
heap->use_custom_heap = ZEND_MM_CUSTOM_HEAP_NONE;
21002130
#endif
21012131
#if ZEND_MM_STORAGE
2102-
heap->storage = NULL;
2132+
ZEND_MM_RO_HEAP(heap)->storage = NULL;
21032133
#endif
21042134
heap->huge_list = NULL;
21052135
heap->pid = getpid();
2136+
2137+
mprotect(ZEND_MM_RO_HEAP(heap), zend_mm_get_page_size(), PROT_READ);
2138+
21062139
return heap;
21072140
}
21082141

@@ -2431,7 +2464,7 @@ void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent)
24312464

24322465
#if ZEND_MM_CUSTOM
24332466
if (heap->use_custom_heap) {
2434-
if (heap->custom_heap._malloc == tracked_malloc) {
2467+
if (ZEND_MM_RO_HEAP(heap)->custom_heap._malloc == tracked_malloc) {
24352468
if (silent) {
24362469
tracked_free_all();
24372470
}
@@ -2440,13 +2473,15 @@ void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent)
24402473
zend_hash_destroy(heap->tracked_allocs);
24412474
free(heap->tracked_allocs);
24422475
/* Make sure the heap free below does not use tracked_free(). */
2443-
heap->custom_heap._free = __zend_free;
2476+
mprotect(ZEND_MM_RO_HEAP(heap), zend_mm_get_page_size(), PROT_WRITE);
2477+
ZEND_MM_RO_HEAP(heap)->custom_heap._free = __zend_free;
2478+
mprotect(ZEND_MM_RO_HEAP(heap), zend_mm_get_page_size(), PROT_READ);
24442479
}
24452480
heap->size = 0;
24462481
}
24472482

24482483
if (full) {
2449-
heap->custom_heap._free(heap ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
2484+
ZEND_MM_RO_HEAP(heap)->custom_heap._free(heap ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
24502485
}
24512486
return;
24522487
}
@@ -2511,7 +2546,7 @@ void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent)
25112546

25122547
/* reinitialize the first chunk and heap */
25132548
p = heap->main_chunk;
2514-
p->heap = &p->heap_slot;
2549+
//p->heap = &p->heap_slot;
25152550
p->next = p;
25162551
p->prev = p;
25172552
p->free_pages = ZEND_MM_PAGES - ZEND_MM_FIRST_PAGE;
@@ -2575,7 +2610,7 @@ ZEND_API size_t ZEND_FASTCALL _zend_mm_block_size(zend_mm_heap *heap, void *ptr
25752610
{
25762611
#if ZEND_MM_CUSTOM
25772612
if (UNEXPECTED(heap->use_custom_heap)) {
2578-
if (heap->custom_heap._malloc == tracked_malloc) {
2613+
if (ZEND_MM_RO_HEAP(heap)->custom_heap._malloc == tracked_malloc) {
25792614
zend_ulong h = ((uintptr_t) ptr) >> ZEND_MM_ALIGNMENT_LOG2;
25802615
zval *size_zv = zend_hash_index_find(heap->tracked_allocs, h);
25812616
if (size_zv) {
@@ -2618,7 +2653,7 @@ ZEND_API bool is_zend_ptr(const void *ptr)
26182653
{
26192654
#if ZEND_MM_CUSTOM
26202655
if (AG(mm_heap)->use_custom_heap) {
2621-
if (AG(mm_heap)->custom_heap._malloc == tracked_malloc) {
2656+
if (ZEND_MM_RO_HEAP(AG(mm_heap))->custom_heap._malloc == tracked_malloc) {
26222657
zend_ulong h = ((uintptr_t) ptr) >> ZEND_MM_ALIGNMENT_LOG2;
26232658
zval *size_zv = zend_hash_index_find(AG(mm_heap)->tracked_allocs, h);
26242659
if (size_zv) {
@@ -2661,12 +2696,12 @@ ZEND_API bool is_zend_ptr(const void *ptr)
26612696
#if ZEND_MM_CUSTOM
26622697
# define ZEND_MM_CUSTOM_ALLOCATOR(size) do { \
26632698
if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { \
2664-
return AG(mm_heap)->custom_heap._malloc(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
2699+
return ZEND_MM_RO_HEAP(AG(mm_heap))->custom_heap._malloc(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
26652700
} \
26662701
} while (0)
26672702
# define ZEND_MM_CUSTOM_DEALLOCATOR(ptr) do { \
26682703
if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { \
2669-
AG(mm_heap)->custom_heap._free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
2704+
ZEND_MM_RO_HEAP(AG(mm_heap))->custom_heap._free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
26702705
return; \
26712706
} \
26722707
} while (0)
@@ -2762,7 +2797,7 @@ ZEND_API void* ZEND_FASTCALL _emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LI
27622797
{
27632798
#if ZEND_MM_CUSTOM
27642799
if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) {
2765-
return AG(mm_heap)->custom_heap._malloc(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
2800+
return ZEND_MM_RO_HEAP(AG(mm_heap))->custom_heap._malloc(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
27662801
}
27672802
#endif
27682803
return zend_mm_alloc_heap(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
@@ -2772,7 +2807,7 @@ ZEND_API void ZEND_FASTCALL _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_OR
27722807
{
27732808
#if ZEND_MM_CUSTOM
27742809
if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) {
2775-
AG(mm_heap)->custom_heap._free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2810+
ZEND_MM_RO_HEAP(AG(mm_heap))->custom_heap._free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
27762811
return;
27772812
}
27782813
#endif
@@ -2783,7 +2818,7 @@ ZEND_API void* ZEND_FASTCALL _erealloc(void *ptr, size_t size ZEND_FILE_LINE_DC
27832818
{
27842819
#if ZEND_MM_CUSTOM
27852820
if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) {
2786-
return AG(mm_heap)->custom_heap._realloc(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2821+
return ZEND_MM_RO_HEAP(AG(mm_heap))->custom_heap._realloc(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
27872822
}
27882823
#endif
27892824
return zend_mm_realloc_heap(AG(mm_heap), ptr, size, 0, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
@@ -2793,7 +2828,7 @@ ZEND_API void* ZEND_FASTCALL _erealloc2(void *ptr, size_t size, size_t copy_size
27932828
{
27942829
#if ZEND_MM_CUSTOM
27952830
if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) {
2796-
return AG(mm_heap)->custom_heap._realloc(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2831+
return ZEND_MM_RO_HEAP(AG(mm_heap))->custom_heap._realloc(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
27972832
}
27982833
#endif
27992834
return zend_mm_realloc_heap(AG(mm_heap), ptr, size, 1, copy_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
@@ -3057,25 +3092,28 @@ static void alloc_globals_ctor(zend_alloc_globals *alloc_globals)
30573092
tmp = getenv("USE_ZEND_ALLOC");
30583093
if (tmp && !ZEND_ATOL(tmp)) {
30593094
bool tracked = (tmp = getenv("USE_TRACKED_ALLOC")) && ZEND_ATOL(tmp);
3060-
zend_mm_heap *mm_heap = alloc_globals->mm_heap = malloc(sizeof(zend_mm_heap));
3095+
ZEND_ASSERT(sizeof(zend_mm_heap) <= zend_mm_get_page_size());
3096+
zend_mm_heap *mm_heap = alloc_globals->mm_heap = malloc(zend_mm_get_page_size() * 2);
30613097
memset(mm_heap, 0, sizeof(zend_mm_heap));
30623098
mm_heap->use_custom_heap = ZEND_MM_CUSTOM_HEAP_STD;
30633099
mm_heap->limit = (size_t)Z_L(-1) >> 1;
30643100
mm_heap->overflow = 0;
30653101

3102+
mprotect(ZEND_MM_RO_HEAP(mm_heap), zend_mm_get_page_size(), PROT_WRITE);
30663103
if (!tracked) {
30673104
/* Use system allocator. */
3068-
mm_heap->custom_heap._malloc = __zend_malloc;
3069-
mm_heap->custom_heap._free = __zend_free;
3070-
mm_heap->custom_heap._realloc = __zend_realloc;
3105+
ZEND_MM_RO_HEAP(mm_heap)->custom_heap._malloc = __zend_malloc;
3106+
ZEND_MM_RO_HEAP(mm_heap)->custom_heap._free = __zend_free;
3107+
ZEND_MM_RO_HEAP(mm_heap)->custom_heap._realloc = __zend_realloc;
30713108
} else {
30723109
/* Use system allocator and track allocations for auto-free. */
3073-
mm_heap->custom_heap._malloc = tracked_malloc;
3074-
mm_heap->custom_heap._free = tracked_free;
3075-
mm_heap->custom_heap._realloc = tracked_realloc;
3110+
ZEND_MM_RO_HEAP(mm_heap)->custom_heap._malloc = tracked_malloc;
3111+
ZEND_MM_RO_HEAP(mm_heap)->custom_heap._free = tracked_free;
3112+
ZEND_MM_RO_HEAP(mm_heap)->custom_heap._realloc = tracked_realloc;
30763113
mm_heap->tracked_allocs = malloc(sizeof(HashTable));
30773114
zend_hash_init(mm_heap->tracked_allocs, 1024, NULL, NULL, 1);
30783115
}
3116+
mprotect(ZEND_MM_RO_HEAP(mm_heap), zend_mm_get_page_size(), PROT_READ);
30793117
return;
30803118
}
30813119
#endif
@@ -3145,9 +3183,11 @@ ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
31453183
_heap->use_custom_heap = ZEND_MM_CUSTOM_HEAP_NONE;
31463184
} else {
31473185
_heap->use_custom_heap = ZEND_MM_CUSTOM_HEAP_STD;
3148-
_heap->custom_heap._malloc = _malloc;
3149-
_heap->custom_heap._free = _free;
3150-
_heap->custom_heap._realloc = _realloc;
3186+
mprotect(ZEND_MM_RO_HEAP(_heap), zend_mm_get_page_size(), PROT_WRITE);
3187+
ZEND_MM_RO_HEAP(_heap)->custom_heap._malloc = _malloc;
3188+
ZEND_MM_RO_HEAP(_heap)->custom_heap._free = _free;
3189+
ZEND_MM_RO_HEAP(_heap)->custom_heap._realloc = _realloc;
3190+
mprotect(ZEND_MM_RO_HEAP(_heap), zend_mm_get_page_size(), PROT_READ);
31513191
}
31523192
#endif
31533193
}
@@ -3161,9 +3201,9 @@ ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap,
31613201
zend_mm_heap *_heap = (zend_mm_heap*)heap;
31623202

31633203
if (heap->use_custom_heap) {
3164-
*_malloc = _heap->custom_heap._malloc;
3165-
*_free = _heap->custom_heap._free;
3166-
*_realloc = _heap->custom_heap._realloc;
3204+
*_malloc = ZEND_MM_RO_HEAP(_heap)->custom_heap._malloc;
3205+
*_free = ZEND_MM_RO_HEAP(_heap)->custom_heap._free;
3206+
*_realloc = ZEND_MM_RO_HEAP(_heap)->custom_heap._realloc;
31673207
} else {
31683208
*_malloc = NULL;
31693209
*_free = NULL;
@@ -3179,7 +3219,7 @@ ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap,
31793219
ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap)
31803220
{
31813221
#if ZEND_MM_STORAGE
3182-
return heap->storage;
3222+
return ZEND_MM_RO_HEAP(heap)->storage;
31833223
#else
31843224
return NULL
31853225
#endif
@@ -3195,7 +3235,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
31953235
#if ZEND_MM_STORAGE
31963236
zend_mm_storage tmp_storage, *storage;
31973237
zend_mm_chunk *chunk;
3198-
zend_mm_heap *heap;
3238+
zend_mm_heap *heap = (zend_mm_heap*)zend_mm_chunk_alloc_int(REAL_PAGE_SIZE * 2, REAL_PAGE_SIZE);
31993239

32003240
memcpy((zend_mm_handlers*)&tmp_storage.handlers, handlers, sizeof(zend_mm_handlers));
32013241
tmp_storage.data = data;
@@ -3206,7 +3246,6 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
32063246
#endif
32073247
return NULL;
32083248
}
3209-
heap = &chunk->heap_slot;
32103249
chunk->heap = heap;
32113250
chunk->next = chunk;
32123251
chunk->prev = chunk;
@@ -3239,7 +3278,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
32393278
#if ZEND_MM_CUSTOM
32403279
heap->use_custom_heap = 0;
32413280
#endif
3242-
heap->storage = &tmp_storage;
3281+
ZEND_MM_RO_HEAP(heap)->storage = &tmp_storage;
32433282
heap->huge_list = NULL;
32443283
memset(heap->free_slot, 0, sizeof(heap->free_slot));
32453284
storage = _zend_mm_alloc(heap, sizeof(zend_mm_storage) + data_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_CC);
@@ -3255,8 +3294,9 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
32553294
storage->data = (void*)(((char*)storage + sizeof(zend_mm_storage)));
32563295
memcpy(storage->data, data, data_size);
32573296
}
3258-
heap->storage = storage;
3297+
ZEND_MM_RO_HEAP(heap)->storage = storage;
32593298
heap->pid = getpid();
3299+
mprotect(ZEND_MM_RO_HEAP(heap), zend_mm_get_page_size(), PROT_READ);
32603300
return heap;
32613301
#else
32623302
return NULL;

Zend/zend_alloc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ ZEND_API void zend_memory_reset_peak_usage(void);
242242

243243
/* Heap functions */
244244
typedef struct _zend_mm_heap zend_mm_heap;
245+
typedef struct _zend_mm_ro_heap zend_mm_ro_heap;
245246

246247
ZEND_API zend_mm_heap *zend_mm_startup(void);
247248
ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, bool full_shutdown, bool silent);

0 commit comments

Comments
 (0)