From: Vladimir Davydov <vdavydov.dev@gmail.com> To: Kirill Shcherbatov <kshcherbatov@tarantool.org> Cc: tarantool-patches@freelists.org Subject: Re: [PATCH v2 7/9] box: sandbox option for persistent functions Date: Mon, 10 Jun 2019 17:06:45 +0300 [thread overview] Message-ID: <20190610140645.orrfcqklmum7nhsd@esperanza> (raw) In-Reply-To: <6b79e42320697259d90dfbc4ed0ff79882a857ee.1559822429.git.kshcherbatov@tarantool.org> On Thu, Jun 06, 2019 at 03:04:03PM +0300, Kirill Shcherbatov wrote: > Introduced a new option 'is_sandboxed' to initialize a new > persistent function inside of isolated sandbox where only limited > number of functions and modules is available: > -assert -error -pairs -ipairs -next -pcall -xpcall -type > -print -select -string -tonumber -tostring -unpack -math -utf8 > > Global variables are forbidden in persistent Lua functions. > > To initialize a new persistent function inside of sandbox, > specify is_sandboxed = true: > box.schema.func.create('myfunc', {body = body, > opts = {is_sandboxed = true}}) > > Part of #4182 > Needed for #1260 > --- > src/box/alter.cc | 12 ++++++ > src/box/errcode.h | 1 + > src/box/func.c | 8 ++++ > src/box/func_def.c | 9 +++++ > src/box/func_def.h | 23 +++++++++++ > src/lua/utils.c | 67 +++++++++++++++++++++++++++++++ > src/lua/utils.h | 8 ++++ > test/box/misc.result | 1 + > test/box/persistent_func.result | 36 +++++++++++++++++ > test/box/persistent_func.test.lua | 15 +++++++ > 10 files changed, 180 insertions(+) > > diff --git a/src/box/alter.cc b/src/box/alter.cc > index 11cad77c3..c769e4f3d 100644 > --- a/src/box/alter.cc > +++ b/src/box/alter.cc > @@ -2449,6 +2449,7 @@ func_def_new_from_tuple(struct tuple *tuple) > if (def == NULL) > tnt_raise(OutOfMemory, def_sz, "malloc", "def"); > auto def_guard = make_scoped_guard([=] { free(def); }); > + func_opts_create(&def->opts); > func_def_get_ids_from_tuple(tuple, &def->fid, &def->uid); > memcpy(def->name, name, name_len); > def->name[name_len] = 0; > @@ -2492,6 +2493,17 @@ func_def_new_from_tuple(struct tuple *tuple) > } > def->is_deterministic = > tuple_field_bool_xc(tuple, BOX_FUNC_FIELD_IS_DETERMINISTIC); > + const char *opts = tuple_field(tuple, BOX_FUNC_FIELD_OPTS); > + if (opts_decode(&def->opts, func_opts_reg, &opts, > + ER_WRONG_FUNCTION_OPTIONS, BOX_FUNC_FIELD_OPTS, > + NULL) != 0) > + diag_raise(); > + if (def->opts.is_sandboxed && > + (def->language != FUNC_LANGUAGE_LUA || body_len == 0)) { > + tnt_raise(ClientError, ER_CREATE_FUNCTION, name, > + "is_sandboxed option is applieble only for " > + "persistent Lua function"); > + } Again, the check should be carried out in function constructors so that we don't change this code when we introduce SQL functions. > } else { > def->returns = FIELD_TYPE_ANY; > def->is_deterministic = false; > diff --git a/src/box/func_def.c b/src/box/func_def.c > index 76ed77b24..df74a6d9a 100644 > --- a/src/box/func_def.c > +++ b/src/box/func_def.c > @@ -1,3 +1,12 @@ > #include "func_def.h" > +#include "opt_def.h" > > const char *func_language_strs[] = {"LUA", "C"}; > + > +const struct func_opts func_opts_default = { > + /* .is_sandboxed = */ false, > +}; > + > +const struct opt_def func_opts_reg[] = { > + OPT_DEF("is_sandboxed", OPT_BOOL, struct func_opts, is_sandboxed), > +}; AFAIK we've decided to make all function options as tuple fields while the 'option' field is here just in case we need to add something later. > diff --git a/src/lua/utils.c b/src/lua/utils.c > index 27ff6b396..0d1cca423 100644 > --- a/src/lua/utils.c > +++ b/src/lua/utils.c > @@ -46,6 +46,14 @@ static uint32_t CTID_STRUCT_IBUF_PTR; > uint32_t CTID_CHAR_PTR; > uint32_t CTID_CONST_CHAR_PTR; > > +static const char *default_sandbox_exports[] = > + {"assert", "error", "ipairs", "math", "next", "pairs", "pcall", > + "print", "select", "string", "table", "tonumber", "tostring", > + "type", "unpack", "xpcall", "utf8"}; > + > +static int luaL_deepcopy_func_ref = LUA_REFNIL; > +static int luaL_default_sandbox_ref = LUA_REFNIL; > + > void * > luaL_pushcdata(struct lua_State *L, uint32_t ctypeid) > { > @@ -1248,6 +1256,65 @@ luaT_func_find(struct lua_State *L, const char *name, const char *name_end, > return 0; > } > > +/** > + * Assemble a new sandbox with given exports table on top of the > + * Lua stack. All modules in exports list are copying deeply > + * to ensure the immutablility of this system object. > + */ > +static int > +luaT_prepare_sandbox(struct lua_State *L, const char *exports[], > + uint32_t exports_count) > +{ > + assert(luaL_deepcopy_func_ref != LUA_REFNIL); > + lua_createtable(L, exports_count, 0); > + for (unsigned i = 0; i < exports_count; i++) { > + int count; > + uint32_t name_len = strlen(exports[i]); > + if (luaT_func_find(L, exports[i], exports[i] + name_len, > + &count) != 0) > + return -1; > + switch (lua_type(L, -1)) { > + case LUA_TTABLE: > + lua_rawgeti(L, LUA_REGISTRYINDEX, > + luaL_deepcopy_func_ref); > + lua_insert(L, -2); > + lua_call(L, 1, LUA_MULTRET); > + FALLTHROUGH; > + case LUA_TFUNCTION: > + break; > + default: > + unreachable(); > + } > + lua_setfield(L, -2, exports[i]); > + } > + return 0; > +} > + > +int > +luaT_get_sandbox(struct lua_State *L) As I mentioned earlier, I don't think we need to have these highly specialized functions in src/lua/util.[hc]. I'd define them as static in src/box/lua/call.[hc] as we only need them to invoke persistent Lua functions. > +{ > + if (luaL_deepcopy_func_ref == LUA_REFNIL) { > + int count; > + const char *deepcopy = "table.deepcopy"; > + if (luaT_func_find(L, deepcopy, deepcopy + strlen(deepcopy), > + &count) != 0) > + return -1; Wouldn't it be more effecient to copy the table in C, i.e. without the aid of 'table.deepcopy' method? > + luaL_deepcopy_func_ref = luaL_ref(L, LUA_REGISTRYINDEX); > + assert(luaL_deepcopy_func_ref != LUA_REFNIL); > + } > + if (luaL_default_sandbox_ref == LUA_REFNIL) { > + if (luaT_prepare_sandbox(L, default_sandbox_exports, > + nelem(default_sandbox_exports)) != 0) > + return -1; > + luaL_default_sandbox_ref = luaL_ref(L, LUA_REGISTRYINDEX); > + assert(luaL_default_sandbox_ref != LUA_REFNIL); > + } > + lua_rawgeti(L, LUA_REGISTRYINDEX, luaL_deepcopy_func_ref); > + lua_rawgeti(L, LUA_REGISTRYINDEX, luaL_default_sandbox_ref); > + lua_call(L, 1, LUA_MULTRET); > + return 0; > +}
next prev parent reply other threads:[~2019-06-10 14:06 UTC|newest] Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-06-06 12:03 [PATCH v2 0/9] box: rework functions machinery Kirill Shcherbatov 2019-06-06 12:03 ` [PATCH v2 1/9] box: refactor box_lua_find helper Kirill Shcherbatov 2019-06-10 9:17 ` Vladimir Davydov 2019-06-06 12:03 ` [PATCH v2 2/9] box: move box_module_reload routine to func.c Kirill Shcherbatov 2019-06-10 9:19 ` Vladimir Davydov 2019-06-06 12:03 ` [PATCH v2 3/9] box: rework func cache update machinery Kirill Shcherbatov 2019-06-10 9:44 ` Vladimir Davydov 2019-06-06 12:04 ` [PATCH v2 4/9] box: rework func object as a function frontend Kirill Shcherbatov 2019-06-10 10:32 ` Vladimir Davydov 2019-06-06 12:04 ` [PATCH v2 5/9] schema: rework _func system space format Kirill Shcherbatov 2019-06-10 12:10 ` Vladimir Davydov 2019-06-06 12:04 ` [PATCH v2 6/9] box: load persistent Lua functions on creation Kirill Shcherbatov 2019-06-10 12:19 ` Vladimir Davydov 2019-06-06 12:04 ` [PATCH v2 7/9] box: sandbox option for persistent functions Kirill Shcherbatov 2019-06-10 14:06 ` Vladimir Davydov [this message] 2019-06-10 14:15 ` [tarantool-patches] " Kirill Shcherbatov 2019-06-10 14:41 ` Vladimir Davydov 2019-06-06 12:04 ` [PATCH v2 8/9] box: implement lua_port dump to region and to Lua Kirill Shcherbatov 2019-06-10 14:24 ` Vladimir Davydov 2019-06-06 12:04 ` [PATCH v2 9/9] box: export _func functions with box.func folder Kirill Shcherbatov 2019-06-10 15:18 ` Vladimir Davydov 2019-06-10 9:14 ` [PATCH v2 0/9] box: rework functions machinery Vladimir Davydov
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20190610140645.orrfcqklmum7nhsd@esperanza \ --to=vdavydov.dev@gmail.com \ --cc=kshcherbatov@tarantool.org \ --cc=tarantool-patches@freelists.org \ --subject='Re: [PATCH v2 7/9] box: sandbox option for persistent functions' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox