From 4123061bc95baa21e013ed1fd72867e4fcde8068 Mon Sep 17 00:00:00 2001
From: Vladimir Davydov <vdavydov@tarantool.org>
Date: Wed, 16 Aug 2023 15:03:06 +0300
Subject: [PATCH] lua: fix heap-use-after-free bug in tuple format constructor

Runtime tuple formats are reusable, which means that a tuple format
returned by runtime_tuple_format_new may not be brand new, but actually
be used by a Lua object. As a result, if we call any function that may
trigger Lua GC between runtime_tuple_format_new and tuple_format_ref,
the tuple format may be deleted, leading to a use-after-free bug. This
is what happens in lbox_tuple_format_new. Fix this issue by taking a
reference to the format before pushing a cdata object to the Lua stack
in lbox_push_tuple_format.

The issue was fixed in the master branch by commit 28ec245d0a7e ("lua:
fix heap-use-after-free bug in tuple format constructor"). This isn't
a clean cherry-pick because the code changed quite a bit.

Closes #8889

NO_DOC=bug fix
NO_TEST=difficult to reproduce, found by ASAN
---
 .../unreleased/gh-8889-lua-box-tuple-format-new-fix.md    | 4 ++++
 src/box/lua/misc.cc                                       | 8 +++++++-
 2 files changed, 11 insertions(+), 1 deletion(-)
 create mode 100644 changelogs/unreleased/gh-8889-lua-box-tuple-format-new-fix.md

diff --git a/changelogs/unreleased/gh-8889-lua-box-tuple-format-new-fix.md b/changelogs/unreleased/gh-8889-lua-box-tuple-format-new-fix.md
new file mode 100644
index 0000000000..cd32ef42d3
--- /dev/null
+++ b/changelogs/unreleased/gh-8889-lua-box-tuple-format-new-fix.md
@@ -0,0 +1,4 @@
+## bugfix/lua/netbox
+
+* Fixed a heap-use-after-free bug in the function creating a tuple format Lua
+  object for `net.box` (gh-8889).
diff --git a/src/box/lua/misc.cc b/src/box/lua/misc.cc
index c84613249d..a9a5ab01d7 100644
--- a/src/box/lua/misc.cc
+++ b/src/box/lua/misc.cc
@@ -371,10 +371,16 @@ lbox_tuple_format_gc(struct lua_State *L)
 static int
 lbox_push_tuple_format(struct lua_State *L, struct tuple_format *format)
 {
+	/*
+	 * Tuple formats are reusable. It means that runtime_tuple_format_new
+	 * may return a format that is actually referenced by another Lua
+	 * object. So we have to be extra careful not to call anything that may
+	 * trigger Lua GC after we create a format and before we reference it.
+	 */
+	tuple_format_ref(format);
 	struct tuple_format **ptr = (struct tuple_format **)
 		luaL_pushcdata(L, CTID_STRUCT_TUPLE_FORMAT_PTR);
 	*ptr = format;
-	tuple_format_ref(format);
 	lua_pushcfunction(L, lbox_tuple_format_gc);
 	luaL_setcdatagc(L, -2);
 	return 1;
-- 
GitLab