Skip to content
Snippets Groups Projects
Commit 08565b5c authored by Nikolay Shirokovskiy's avatar Nikolay Shirokovskiy Committed by Vladimir Davydov
Browse files

fiber: fix use-after-free on fiber destroy/recycle

When fiber region is freed/destroyed and ENABLE_BACKTRACE is set then
`fiber_on_gc_truncate` callback is called. At this time both `used`
argument and `fiber->gc_initial_size` are equal to 0. Thus
`fiber->first_alloc_bt` is accessed which is already freed.

With a bad luck freeing fiber region can put slab back into slab arena.
So writing after free can change memory used by another thread.

Closes #9020

NO_TEST=tested by ASAN
NO_DOC=bugfix

(cherry picked from commit c480a867)
parent a3600f5e
No related branches found
No related tags found
No related merge requests found
## bugfix/core
* Fixed a use-after-free bug in fiber recycling code (gh-9020).
...@@ -931,14 +931,13 @@ fiber_recycle(struct fiber *fiber) ...@@ -931,14 +931,13 @@ fiber_recycle(struct fiber *fiber)
fiber->storage.lua.fid_ref = FIBER_LUA_NOREF; fiber->storage.lua.fid_ref = FIBER_LUA_NOREF;
unregister_fid(fiber); unregister_fid(fiber);
fiber->fid = 0; fiber->fid = 0;
/* Set before free to disable truncation system area check. */
fiber->gc_initial_size = 0; fiber->gc_initial_size = 0;
region_free(&fiber->gc);
#ifdef ENABLE_BACKTRACE #ifdef ENABLE_BACKTRACE
fiber->parent_bt = NULL; fiber->parent_bt = NULL;
fiber->first_alloc_bt = NULL; fiber->first_alloc_bt = NULL;
region_set_callbacks(&fiber->gc, NULL, NULL, NULL); region_set_callbacks(&fiber->gc, NULL, NULL, NULL);
#endif #endif
region_free(&fiber->gc);
if (fiber_is_reusable(fiber->flags)) { if (fiber_is_reusable(fiber->flags)) {
rlist_move_entry(&cord()->dead, fiber, link); rlist_move_entry(&cord()->dead, fiber, link);
} else { } else {
...@@ -1459,8 +1458,9 @@ fiber_destroy(struct cord *cord, struct fiber *f) ...@@ -1459,8 +1458,9 @@ fiber_destroy(struct cord *cord, struct fiber *f)
trigger_destroy(&f->on_stop); trigger_destroy(&f->on_stop);
rlist_del(&f->state); rlist_del(&f->state);
rlist_del(&f->link); rlist_del(&f->link);
/* Set before free to disable truncation system area check. */ #ifdef ENABLE_BACKTRACE
f->gc_initial_size = 0; region_set_callbacks(&f->gc, NULL, NULL, NULL);
#endif
region_destroy(&f->gc); region_destroy(&f->gc);
fiber_stack_destroy(f, &cord->slabc); fiber_stack_destroy(f, &cord->slabc);
diag_destroy(&f->diag); diag_destroy(&f->diag);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment