Skip to content

Commit

Permalink
Fix bug #81068: Fix possible use-after-free in realpath_cache_clean()
Browse files Browse the repository at this point in the history
If ZTS is enabled, this can cause cwd_globals_ctor() to be called
multiple times, each with a freshly allocated virtual_cwd_globals
instance. At shutdown time however, cwd_globals_dtor() will call
realpath_cache_clean(), which then possibly cleans up the same
realpath_cache instance more than once. Using AddressSanitzer, this
shows up as a heap use-after-free.

To avoid this, add a helper function to do the actual work on one
instance of a realpath_cache, and call it both from cwd_globals_dtor()
and realpath_cache_clean(). The former uses the virtual_cwd_globals
parameter passed in via the destructor, the latter uses the CWDG()
macro.
  • Loading branch information
DimitryAndric authored and nikic committed May 25, 2021
1 parent 59522ba commit 99a2085
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 13 deletions.
3 changes: 3 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 7.4.21

- Core:
. Fixed bug #81068 (Double free in realpath_cache_clean()). (Dimitry Andric)

- Standard:
. Fixed bug #81048 (phpinfo(INFO_VARIABLES) "Array to string conversion").
(cmb)
Expand Down
31 changes: 18 additions & 13 deletions Zend/zend_virtual_cwd.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,25 @@ static void cwd_globals_ctor(virtual_cwd_globals *cwd_g) /* {{{ */
}
/* }}} */

static void realpath_cache_clean_helper(uint32_t max_entries, realpath_cache_bucket **cache, zend_long *cache_size)
{
uint32_t i;

for (i = 0; i < max_entries; i++) {
realpath_cache_bucket *p = cache[i];
while (p != NULL) {
realpath_cache_bucket *r = p;
p = p->next;
free(r);
}
cache[i] = NULL;
}
*cache_size = 0;
}

static void cwd_globals_dtor(virtual_cwd_globals *cwd_g) /* {{{ */
{
realpath_cache_clean();
realpath_cache_clean_helper(sizeof(cwd_g->realpath_cache)/sizeof(cwd_g->realpath_cache[0]), cwd_g->realpath_cache, &cwd_g->realpath_cache_size);
}
/* }}} */

Expand Down Expand Up @@ -346,18 +362,7 @@ static inline zend_ulong realpath_cache_key(const char *path, size_t path_len) /

CWD_API void realpath_cache_clean(void) /* {{{ */
{
uint32_t i;

for (i = 0; i < sizeof(CWDG(realpath_cache))/sizeof(CWDG(realpath_cache)[0]); i++) {
realpath_cache_bucket *p = CWDG(realpath_cache)[i];
while (p != NULL) {
realpath_cache_bucket *r = p;
p = p->next;
free(r);
}
CWDG(realpath_cache)[i] = NULL;
}
CWDG(realpath_cache_size) = 0;
realpath_cache_clean_helper(sizeof(CWDG(realpath_cache))/sizeof(CWDG(realpath_cache)[0]), CWDG(realpath_cache), &CWDG(realpath_cache_size));
}
/* }}} */

Expand Down

0 comments on commit 99a2085

Please sign in to comment.