From 08565b5cb95424c68a3f26adf68e5b2e340b00c1 Mon Sep 17 00:00:00 2001 From: Nikolay Shirokovskiy <nshirokovskiy@tarantool.org> Date: Mon, 19 Jun 2023 10:52:20 +0300 Subject: [PATCH] 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 c480a867680f27e77bfb06efa6c9208c08681329) --- .../gh-9020-fix-use-after-free-on-fiber-finish.md | 3 +++ src/lib/core/fiber.c | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 changelogs/unreleased/gh-9020-fix-use-after-free-on-fiber-finish.md diff --git a/changelogs/unreleased/gh-9020-fix-use-after-free-on-fiber-finish.md b/changelogs/unreleased/gh-9020-fix-use-after-free-on-fiber-finish.md new file mode 100644 index 0000000000..71fc747a99 --- /dev/null +++ b/changelogs/unreleased/gh-9020-fix-use-after-free-on-fiber-finish.md @@ -0,0 +1,3 @@ +## bugfix/core + +* Fixed a use-after-free bug in fiber recycling code (gh-9020). diff --git a/src/lib/core/fiber.c b/src/lib/core/fiber.c index 3694e0bbdc..50ec73c783 100644 --- a/src/lib/core/fiber.c +++ b/src/lib/core/fiber.c @@ -931,14 +931,13 @@ fiber_recycle(struct fiber *fiber) fiber->storage.lua.fid_ref = FIBER_LUA_NOREF; unregister_fid(fiber); fiber->fid = 0; - /* Set before free to disable truncation system area check. */ fiber->gc_initial_size = 0; - region_free(&fiber->gc); #ifdef ENABLE_BACKTRACE fiber->parent_bt = NULL; fiber->first_alloc_bt = NULL; region_set_callbacks(&fiber->gc, NULL, NULL, NULL); #endif + region_free(&fiber->gc); if (fiber_is_reusable(fiber->flags)) { rlist_move_entry(&cord()->dead, fiber, link); } else { @@ -1459,8 +1458,9 @@ fiber_destroy(struct cord *cord, struct fiber *f) trigger_destroy(&f->on_stop); rlist_del(&f->state); rlist_del(&f->link); - /* Set before free to disable truncation system area check. */ - f->gc_initial_size = 0; +#ifdef ENABLE_BACKTRACE + region_set_callbacks(&f->gc, NULL, NULL, NULL); +#endif region_destroy(&f->gc); fiber_stack_destroy(f, &cord->slabc); diag_destroy(&f->diag); -- GitLab