Explicitly store real map ptr base

If we only store the biased pointer, the map ptr region will not
be recognized as reachable memory by leak checkers. This is
primarily problematic for fuzzing, because this is persistent
memory that may be reallocated during the request, without being
an actual leak.

Avoid this by simply storing both the real base pointer of the
allocation, as well as the biased base pointer used for accesses.
This commit is contained in:
Nikita Popov 2021-08-26 12:27:25 +02:00
parent 9cd6c57ad1
commit 6434c93a27
4 changed files with 36 additions and 32 deletions

View file

@ -704,15 +704,16 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals) /* {{
#if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
/* Map region is going to be created and resized at run-time. */
ZEND_MAP_PTR_SET_REAL_BASE(compiler_globals->map_ptr_base, NULL);
compiler_globals->map_ptr_real_base = NULL;
compiler_globals->map_ptr_base = ZEND_MAP_PTR_BIASED_BASE(NULL);
compiler_globals->map_ptr_size = 0;
compiler_globals->map_ptr_last = global_map_ptr_last;
if (compiler_globals->map_ptr_last) {
/* Allocate map_ptr table */
void *base;
compiler_globals->map_ptr_size = ZEND_MM_ALIGNED_SIZE_EX(compiler_globals->map_ptr_last, 4096);
base = pemalloc(compiler_globals->map_ptr_size * sizeof(void*), 1);
ZEND_MAP_PTR_SET_REAL_BASE(compiler_globals->map_ptr_base, base);
void *base = pemalloc(compiler_globals->map_ptr_size * sizeof(void*), 1);
compiler_globals->map_ptr_real_base = base;
compiler_globals->map_ptr_base = ZEND_MAP_PTR_BIASED_BASE(base);
memset(base, 0, compiler_globals->map_ptr_last * sizeof(void*));
}
#else
@ -739,9 +740,10 @@ static void compiler_globals_dtor(zend_compiler_globals *compiler_globals) /* {{
if (compiler_globals->script_encoding_list) {
pefree((char*)compiler_globals->script_encoding_list, 1);
}
if (ZEND_MAP_PTR_REAL_BASE(compiler_globals->map_ptr_base)) {
free(ZEND_MAP_PTR_REAL_BASE(compiler_globals->map_ptr_base));
ZEND_MAP_PTR_SET_REAL_BASE(compiler_globals->map_ptr_base, NULL);
if (compiler_globals->map_ptr_real_base) {
free(compiler_globals->map_ptr_real_base);
compiler_globals->map_ptr_real_base = NULL;
compiler_globals->map_ptr_base = ZEND_MAP_PTR_BIASED_BASE(NULL);
compiler_globals->map_ptr_size = 0;
}
}
@ -972,10 +974,12 @@ void zend_startup(zend_utility_functions *utility_functions) /* {{{ */
*/
CG(map_ptr_size) = 1024 * 1024; // TODO: initial size ???
CG(map_ptr_last) = 0;
ZEND_MAP_PTR_SET_REAL_BASE(CG(map_ptr_base), pemalloc(CG(map_ptr_size) * sizeof(void*), 1));
CG(map_ptr_real_base) = pemalloc(CG(map_ptr_size) * sizeof(void*), 1);
CG(map_ptr_base) = ZEND_MAP_PTR_BIASED_BASE(CG(map_ptr_real_base));
# elif ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
/* Map region is going to be created and resized at run-time. */
ZEND_MAP_PTR_SET_REAL_BASE(CG(map_ptr_base), NULL);
CG(map_ptr_real_base) = NULL;
CG(map_ptr_base) = ZEND_MAP_PTR_BIASED_BASE(NULL);
CG(map_ptr_size) = 0;
CG(map_ptr_last) = 0;
# else
@ -1057,10 +1061,11 @@ zend_result zend_post_startup(void) /* {{{ */
compiler_globals->function_table = NULL;
free(compiler_globals->class_table);
compiler_globals->class_table = NULL;
if (ZEND_MAP_PTR_REAL_BASE(compiler_globals->map_ptr_base)) {
free(ZEND_MAP_PTR_REAL_BASE(compiler_globals->map_ptr_base));
if (compiler_globals->map_ptr_real_base) {
free(compiler_globals->map_ptr_real_base);
}
ZEND_MAP_PTR_SET_REAL_BASE(compiler_globals->map_ptr_base, NULL);
compiler_globals->map_ptr_real_base = NULL;
compiler_globals->map_ptr_base = ZEND_MAP_PTR_BIASED_BASE(NULL);
if ((script_encoding_list = (zend_encoding **)compiler_globals->script_encoding_list)) {
compiler_globals_ctor(compiler_globals);
compiler_globals->script_encoding_list = (const zend_encoding **)script_encoding_list;
@ -1117,9 +1122,10 @@ void zend_shutdown(void) /* {{{ */
ts_free_id(executor_globals_id);
ts_free_id(compiler_globals_id);
#else
if (ZEND_MAP_PTR_REAL_BASE(CG(map_ptr_base))) {
free(ZEND_MAP_PTR_REAL_BASE(CG(map_ptr_base)));
ZEND_MAP_PTR_SET_REAL_BASE(CG(map_ptr_base), NULL);
if (CG(map_ptr_real_base)) {
free(CG(map_ptr_real_base));
CG(map_ptr_real_base) = NULL;
CG(map_ptr_base) = ZEND_MAP_PTR_BIASED_BASE(NULL);
CG(map_ptr_size) = 0;
}
if (CG(script_encoding_list)) {
@ -1224,7 +1230,7 @@ ZEND_API void zend_activate(void) /* {{{ */
init_executor();
startup_scanner();
if (CG(map_ptr_last)) {
memset(ZEND_MAP_PTR_REAL_BASE(CG(map_ptr_base)), 0, CG(map_ptr_last) * sizeof(void*));
memset(CG(map_ptr_real_base), 0, CG(map_ptr_last) * sizeof(void*));
}
zend_observer_activate();
}
@ -1821,12 +1827,13 @@ ZEND_API void *zend_map_ptr_new(void)
#elif ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
/* Grow map_ptr table */
CG(map_ptr_size) = ZEND_MM_ALIGNED_SIZE_EX(CG(map_ptr_last) + 1, 4096);
ZEND_MAP_PTR_SET_REAL_BASE(CG(map_ptr_base), perealloc(ZEND_MAP_PTR_REAL_BASE(CG(map_ptr_base)), CG(map_ptr_size) * sizeof(void*), 1));
CG(map_ptr_real_base) = perealloc(CG(map_ptr_real_base), CG(map_ptr_size) * sizeof(void*), 1);
CG(map_ptr_base) = ZEND_MAP_PTR_BIASED_BASE(CG(map_ptr_real_base));
#else
# error "Unknown ZEND_MAP_PTR_KIND"
#endif
}
ptr = (void**)ZEND_MAP_PTR_REAL_BASE(CG(map_ptr_base)) + CG(map_ptr_last);
ptr = (void**)CG(map_ptr_real_base) + CG(map_ptr_last);
*ptr = NULL;
CG(map_ptr_last)++;
#if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR
@ -1850,12 +1857,13 @@ ZEND_API void zend_map_ptr_extend(size_t last)
#elif ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
/* Grow map_ptr table */
CG(map_ptr_size) = ZEND_MM_ALIGNED_SIZE_EX(last, 4096);
ZEND_MAP_PTR_SET_REAL_BASE(CG(map_ptr_base), perealloc(ZEND_MAP_PTR_REAL_BASE(CG(map_ptr_base)), CG(map_ptr_size) * sizeof(void*), 1));
CG(map_ptr_real_base) = perealloc(CG(map_ptr_real_base), CG(map_ptr_size) * sizeof(void*), 1);
CG(map_ptr_base) = ZEND_MAP_PTR_BIASED_BASE(CG(map_ptr_real_base));
#else
# error "Unknown ZEND_MAP_PTR_KIND"
#endif
}
ptr = (void**)ZEND_MAP_PTR_REAL_BASE(CG(map_ptr_base)) + CG(map_ptr_last);
ptr = (void**)CG(map_ptr_real_base) + CG(map_ptr_last);
memset(ptr, 0, (last - CG(map_ptr_last)) * sizeof(void*));
CG(map_ptr_last) = last;
}

View file

@ -125,6 +125,7 @@ struct _zend_compiler_globals {
HashTable *memoized_exprs;
int memoize_mode;
void *map_ptr_real_base;
void *map_ptr_base;
size_t map_ptr_size;
size_t map_ptr_last;

View file

@ -57,11 +57,8 @@
} while (0)
# define ZEND_MAP_PTR_SET_IMM(ptr, val) \
ZEND_MAP_PTR_SET(ptr, val)
# define ZEND_MAP_PTR_REAL_BASE(base) \
(base)
# define ZEND_MAP_PTR_SET_REAL_BASE(base, ptr) do { \
base = (ptr); \
} while (0)
# define ZEND_MAP_PTR_BIASED_BASE(real_base) \
(real_base)
#elif ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
# define ZEND_MAP_PTR_NEW_OFFSET() \
((uint32_t)(uintptr_t)zend_map_ptr_new())
@ -84,11 +81,8 @@
void **__p = ZEND_MAP_PTR_OFFSET2PTR((uintptr_t)ZEND_MAP_PTR(ptr)); \
*__p = (val); \
} while (0)
# define ZEND_MAP_PTR_REAL_BASE(base) \
((void*)(((uintptr_t)(base)) + 1))
# define ZEND_MAP_PTR_SET_REAL_BASE(base, ptr) do { \
base = (void*)(((uintptr_t)(ptr)) - 1); \
} while (0)
# define ZEND_MAP_PTR_BIASED_BASE(real_base) \
((void*)(((uintptr_t)(real_base)) - 1))
#else
# error "Unknown ZEND_MAP_PTR_KIND"
#endif

View file

@ -4347,8 +4347,9 @@ static void preload_load(void)
size_t old_map_ptr_last = CG(map_ptr_last);
CG(map_ptr_last) = ZCSG(map_ptr_last);
CG(map_ptr_size) = ZEND_MM_ALIGNED_SIZE_EX(CG(map_ptr_last) + 1, 4096);
ZEND_MAP_PTR_SET_REAL_BASE(CG(map_ptr_base), perealloc(ZEND_MAP_PTR_REAL_BASE(CG(map_ptr_base)), CG(map_ptr_size) * sizeof(void*), 1));
memset((void **) ZEND_MAP_PTR_REAL_BASE(CG(map_ptr_base)) + old_map_ptr_last, 0,
CG(map_ptr_real_base) = perealloc(CG(map_ptr_real_base), CG(map_ptr_size) * sizeof(void*), 1);
CG(map_ptr_base) = ZEND_MAP_PTR_BIASED_BASE(CG(map_ptr_real_base));
memset((void **) CG(map_ptr_real_base) + old_map_ptr_last, 0,
(CG(map_ptr_last) - old_map_ptr_last) * sizeof(void *));
}
}