@@ -296,6 +296,20 @@ static bool zend_mm_use_huge_pages = false;
296
296
*/
297
297
298
298
struct _zend_mm_heap {
299
+ union { /* This union contains security-relevant properties, and is thus made read-only at run-time. */
300
+ struct {
301
+ uintptr_t shadow_key ; /* free slot shadow ptr xor key */
302
+ #if ZEND_MM_CUSTOM
303
+ struct {
304
+ void * (* _malloc )(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC );
305
+ void (* _free )(void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC );
306
+ void * (* _realloc )(void * , size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC );
307
+ } custom_heap ;
308
+ #endif
309
+ };
310
+ char padding [ZEND_MM_PAGE_SIZE ];
311
+ };
312
+
299
313
#if ZEND_MM_CUSTOM
300
314
int use_custom_heap ;
301
315
#endif
@@ -306,7 +320,6 @@ struct _zend_mm_heap {
306
320
size_t size ; /* current memory usage */
307
321
size_t peak ; /* peak memory usage */
308
322
#endif
309
- uintptr_t shadow_key ; /* free slot shadow ptr xor key */
310
323
zend_mm_free_slot * free_slot [ZEND_MM_BINS ]; /* free lists for small sizes */
311
324
#if ZEND_MM_STAT || ZEND_MM_LIMIT
312
325
size_t real_size ; /* current size of allocated pages */
@@ -330,11 +343,6 @@ struct _zend_mm_heap {
330
343
int last_chunks_delete_boundary ; /* number of chunks after last deletion */
331
344
int last_chunks_delete_count ; /* number of deletion over the last boundary */
332
345
#if ZEND_MM_CUSTOM
333
- struct {
334
- void * (* _malloc )(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC );
335
- void (* _free )(void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC );
336
- void * (* _realloc )(void * , size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC );
337
- } custom_heap ;
338
346
HashTable * tracked_allocs ;
339
347
#endif
340
348
pid_t pid ;
@@ -2103,6 +2111,9 @@ static zend_mm_heap *zend_mm_init(void)
2103
2111
#endif
2104
2112
heap -> huge_list = NULL ;
2105
2113
heap -> pid = getpid ();
2114
+
2115
+ mprotect (heap , ZEND_MM_PAGE_SIZE , PROT_READ );
2116
+
2106
2117
return heap ;
2107
2118
}
2108
2119
@@ -2440,7 +2451,9 @@ void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent)
2440
2451
zend_hash_destroy (heap -> tracked_allocs );
2441
2452
free (heap -> tracked_allocs );
2442
2453
/* Make sure the heap free below does not use tracked_free(). */
2454
+ mprotect (heap , ZEND_MM_PAGE_SIZE , PROT_WRITE );
2443
2455
heap -> custom_heap ._free = __zend_free ;
2456
+ mprotect (heap , ZEND_MM_PAGE_SIZE , PROT_READ );
2444
2457
}
2445
2458
heap -> size = 0 ;
2446
2459
}
@@ -3063,6 +3076,7 @@ static void alloc_globals_ctor(zend_alloc_globals *alloc_globals)
3063
3076
mm_heap -> limit = (size_t )Z_L (-1 ) >> 1 ;
3064
3077
mm_heap -> overflow = 0 ;
3065
3078
3079
+ mprotect (mm_heap , ZEND_MM_PAGE_SIZE , PROT_WRITE );
3066
3080
if (!tracked ) {
3067
3081
/* Use system allocator. */
3068
3082
mm_heap -> custom_heap ._malloc = __zend_malloc ;
@@ -3076,6 +3090,7 @@ static void alloc_globals_ctor(zend_alloc_globals *alloc_globals)
3076
3090
mm_heap -> tracked_allocs = malloc (sizeof (HashTable ));
3077
3091
zend_hash_init (mm_heap -> tracked_allocs , 1024 , NULL , NULL , 1 );
3078
3092
}
3093
+ mprotect (mm_heap , ZEND_MM_PAGE_SIZE , PROT_READ );
3079
3094
return ;
3080
3095
}
3081
3096
#endif
@@ -3141,14 +3156,18 @@ ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
3141
3156
#if ZEND_MM_CUSTOM
3142
3157
zend_mm_heap * _heap = (zend_mm_heap * )heap ;
3143
3158
3159
+ mprotect (_heap , ZEND_MM_PAGE_SIZE , PROT_WRITE );
3144
3160
if (!_malloc && !_free && !_realloc ) {
3145
3161
_heap -> use_custom_heap = ZEND_MM_CUSTOM_HEAP_NONE ;
3146
3162
} else {
3147
3163
_heap -> use_custom_heap = ZEND_MM_CUSTOM_HEAP_STD ;
3164
+ mprotect (heap , ZEND_MM_PAGE_SIZE , PROT_WRITE );
3148
3165
_heap -> custom_heap ._malloc = _malloc ;
3149
3166
_heap -> custom_heap ._free = _free ;
3150
3167
_heap -> custom_heap ._realloc = _realloc ;
3168
+ mprotect (heap , ZEND_MM_PAGE_SIZE , PROT_READ );
3151
3169
}
3170
+ mprotect (_heap , ZEND_MM_PAGE_SIZE , PROT_READ );
3152
3171
#endif
3153
3172
}
3154
3173
0 commit comments