Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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)

AltStyle によって変換されたページ (->オリジナル) /