diff --git a/changelogs/unreleased/gh-9406-fix-use-after-free-on-shutdown.md b/changelogs/unreleased/gh-9406-fix-use-after-free-on-shutdown.md new file mode 100644 index 0000000000000000000000000000000000000000..b5f58bc4b248060cae1d75944095ec99128dc5b6 --- /dev/null +++ b/changelogs/unreleased/gh-9406-fix-use-after-free-on-shutdown.md @@ -0,0 +1,4 @@ +## bugfix/core + +* Fixed potential use-after-free on Tarantool shutdown with lingering + fiber join (gh-9406). diff --git a/src/lib/core/fiber.c b/src/lib/core/fiber.c index 5fa2be21265b7ac46d5d1ce7f441fa17f1a04a83..fa0f02abfc4c6ded096be3e1e789a57f630e1457 100644 --- a/src/lib/core/fiber.c +++ b/src/lib/core/fiber.c @@ -1637,6 +1637,7 @@ fiber_destroy(struct cord *cord, struct fiber *f) trigger_destroy(&f->on_stop); rlist_del(&f->state); rlist_del(&f->link); + rlist_del(&f->wake); #ifdef ENABLE_BACKTRACE region_set_callbacks(&f->gc, NULL, NULL, NULL); #endif @@ -1825,6 +1826,7 @@ cord_create(struct cord *cord, const char *name) /* sched fiber is not present in alive/ready/dead list. */ rlist_create(&cord->sched.state); rlist_create(&cord->sched.link); + rlist_create(&cord->sched.wake); cord->sched.fid = FIBER_ID_SCHED; fiber_reset(&cord->sched); diag_create(&cord->sched.diag); diff --git a/test/app-luatest/fiber_test.lua b/test/app-luatest/fiber_test.lua index f42cfb62c9fe9e7c3e1799c55a6d4f7fa445d8b2..8a681b48ed89534f73486a560d7732f96ca23aba 100644 --- a/test/app-luatest/fiber_test.lua +++ b/test/app-luatest/fiber_test.lua @@ -34,3 +34,26 @@ g.test_tostring = function() fiber.yield() t.assert_equals(tostring(f), "fiber: " .. fid .. " (dead)") end + +g.test_gh_9406_shutdown_with_lingering_fiber_join = function() + local script = [[ + local fiber = require('fiber') + + local f = nil + fiber.create(function() + while f == nil do + fiber.sleep(0.1) + end + fiber.join(f) + end) + f = fiber.new(function() + fiber.sleep(1000) + end) + f:set_joinable(true) + fiber.sleep(0.2) + os.exit() + ]] + local tarantool_bin = arg[-1] + local cmd = string.format('%s -e "%s"', tarantool_bin, script) + t.assert(os.execute(cmd) == 0) +end