[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Upgrading C sandbox from 5.1 to 5.2/5.3
- From: Luke Mewburn <luke@...>
- Date: Tue, 10 Feb 2015 09:16:46 +1100
Hi.
Background:
I've been using Lua 5.1 for a few years as a configuration and extension
language for our C++ programs at my work. We have a C++ wrapper
interface that sandboxes the lua script that's loaded from file or
string, and also provides a sandboxed interface to calling out to lua
functions where desired.
The original ideas for the sandbox were derived from my reading
of the various Lua literature available a few years ago when Lua 5.1
was the current release.
I'm seeking advice on the best way to use Lua 5.2 from C/C++
to load chunks in a sandboxed environment and subsequently invoke
lua functions from C/C++ in that same sandbox.
With the change in Lua 5.2 to deprecate lua_setfenv() in favour of other
techniques (upvalues ?), I would like to update the C++ wrapper library
for Lua 5.2/5.3 as well as continuing to support Lua 5.1.
It may be that the pattern I used for Lua 5.1 can't be used for Lua 5.2
and I need to redesign my wrapper library. I'd prefer to do that in a
way that reduces change on callers of the library.
Current use in Lua 5.1:
The sandboxing setup technique used in Lua 5.1 is:
a) create a table for the environment
b) copy names of "safe" globals into the table, such as
assert(), ipairs(), string.*, (etc)
c) add other (private) extensions to the table
d) add the table to the global environment with a well-known name
To invoke a chunk or function
a) limit instructions / maskcount
b) get the sandbox table from the global environment
c) set the environment for the chunk/function with lua_setfenv()
d) call the chunk/function
To lookup a table value (e.g. to obtain t1.t2 from "t1 = { t2 = 5, }")
methods to obtain the values by traversing the sandbox table.
This has been working well for a few years.
Attempt to convert to Lua 5.2:
I've tried converting our use of lua_setfenv() to lua_setupvalue() but
it's not setting up the environment correctly when trying to set
the environment for a function call (versus a chunk call).
lua_setupvalue(L, -3, 1) is returning NULL when the stack has;
1: function
2: table as function argument
3: table to use as environment
I.e. When I change Lua 5.1's
lua_setfenv(L, -iNumArgs - 2))
to Lua 5.2's
lua_setupvalue(L, -iNumArgs - 2, 1)
my sandboxing doesn't work.
Pseudo-code of the Lua 5.1 sandbox technique:
// Construct state
lua_State * setup()
lua_State * L = luaL_newstate();
// sandbox will get a subset of the libs
luaL_openlibs(L);
return L;
// Load string onto stack
loadstring(lua_state * L, const char * str) // (loadfile is similar)
luaL_loadstring(L, str)
callChunk(L);
// Setup sandbox and call chunk on the stack
callChunk(lua_state * LL)
lua_newtable(L) // populate table for sandbox
setupSandbox(L)
lua_setglobal(L, "LuaSandbox"); // store sandbox in global var
sandboxCall(L, 0, 0)
// Call function on stack in a sandbox (maskcount, restricted environment)
sandboxCall(lua_state * L, int iNumArgs, int iNumResults)
lua_sethook(L, &maskcount, LUA_MASKCOUNT, someLimit);
lua_getglobal(L, "LuaSandBox"); // set environment to sandbox
lua_setfenv(L, -iNumArgs - 2);
lua_pcall(L, iNumArgs, iNumResults);
lua_sethook(L, &maskcount, LUA_MASKCOUNT, 0);
// Setup table for use as a sandbox environment. Caller may extend.
setupSandbox(lua_State * L)
// copy values from global environment into sandbox table on stack top
// Call a lua function from C that takes a table argument & returns a bool
fooFunction(lua_State * L)
findName(L, "some_method");
if (! lua_isfunction(L, -1)) error();
lua_createTable(L, 0, 1);
lua_pushstring(L, "some value");
lua_setfield(L, "k"); // { k = "somevalue", }
sandboxCall(L, 1, 1) // invoke some_method({k="somevalue"})
bool result = lua_toboolean(L, -1)
lua_pop(L, 1);
return result;
Regards,
Luke.
Attachment:
pgpiEELFGRnHJ.pgp
Description: PGP signature