C语言 LuaL_openlibs()和沙箱脚本

q5lcpyga  于 2023-06-21  发布在  其他
关注(0)|答案(6)|浏览(119)

我正在将Lua(5.1)嵌入到一个C/C++应用程序中。
我使用LuaL_openlibs()函数来加载基本库。然而,这个函数加载了一些我想禁用的其他库,这样它们就不能用于我的Lua脚本了。
具体来说,我想禁用IO和OS模块。有没有一个函数可以让我通过编程禁用(或卸载)这些模块,这样我就可以创建一个安全的沙箱环境来运行Lua脚本?

wtlkbnrh

wtlkbnrh1#

我不知道如何禁用模块,但您仍然可以选择加载哪些模块,而不是使用luaL_openlibs加载所有模块。Lua 5.1手册的第7.3节说:
luaopen_*函数(用于打开库)不能像常规C函数那样直接调用。它们必须通过Lua调用,就像Lua函数一样。
也就是说,不是像Lua 5.0中那样直接调用函数:

luaopen_table(L);

...你可以将它作为一个C函数使用它的名字,并在Lua 5.1中使用lua_call或类似的东西:

lua_pushcfunction(L, luaopen_table);
lua_pushliteral(L, LUA_TABLIBNAME);
lua_call(L, 1, 0);

可以使用的函数在lualib.h中列出:

Function        | Name
----------------+-----------------
luaopen_base    | ""
luaopen_table   | LUA_TABLIBNAME
luaopen_io      | LUA_IOLIBNAME
luaopen_os      | LUA_OSLIBNAME
luaopen_string  | LUA_STRLIBNAME
luaopen_math    | LUA_MATHLIBNAME
luaopen_debug   | LUA_DBLIBNAME
luaopen_package | LUA_LOADLIBNAME
nx7onnlm

nx7onnlm2#

最简单的解决方案:在加载库后执行io=nil;os=nil

6ioyuze2

6ioyuze23#

在旧版本的Lua中,您可以指定要加载哪些库。具体来说,在我的lualib. h副本中,我看到声明了以下函数:

LUALIB_API int (luaopen_base) (lua_State *L);
LUALIB_API int (luaopen_table) (lua_State *L);
LUALIB_API int (luaopen_io) (lua_State *L);
LUALIB_API int (luaopen_os) (lua_State *L);
LUALIB_API int (luaopen_string) (lua_State *L);
LUALIB_API int (luaopen_math) (lua_State *L);
LUALIB_API int (luaopen_debug) (lua_State *L);
LUALIB_API int (luaopen_package) (lua_State *L);
LUALIB_API void (luaL_openlibs) (lua_State *L);

我无法告诉您不加载所有库的后果,因为我在代码中调用了luaL_openlibs()。第一版的Lua编程可以在线获得,并提到luaL_openlibs()应该取代luaopen_*()函数调用。然而,为了向后兼容性,仍然可以包括较旧的函数。http://www.lua.org/pil/24.1.html
HTH

ffscu2ro

ffscu2ro4#

我的answer to another question也在这里。
从Lua 5.3开始,你需要luaL_requiref这些,基于luaL_openlibs中的源代码。我在任何手册中都没有找到这方面的参考资料。所以这里有一个例子,它只打开了允许lua到print到标准输出的基本库。

#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

int main( int argc, char *argv[] ) {

  lua_State *lua = luaL_newstate();
  luaL_requiref( lua, "_G", luaopen_base, 1 );
  lua_pop( lua, 1 );

  luaL_dostring( lua, "print \"Hello, lua\"" );

  lua_close( lua );

  return 0;
}

例如,除了base之外,您还可以像这样加载I/O库。

luaL_requiref( lua, LUA_IOLIBNAME, luaopen_io, 1 );
lua_pop( lua, 1 );

另请参阅手册。

tzcvj98z

tzcvj98z5#

我想指出的是,包库也应该被禁用。

package.loadlib("/usr/lib/liblua.so.5.1", "lua_call")()

将加载一个C函数,然后用不正确的参数调用它,从而导致segfault。这可能会导致比segfaults更大的问题

xzlaal3s

xzlaal3s6#

luaL_openlibs只是遍历在同一个文件中声明的库加载器列表。只需删除/注解掉luaopen_ioluaopen_os行。好了
如果你不想编辑Lua源代码,那么你可以定义自己的函数,省去这两个库:

#define LUA_LIB

#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"

static const luaL_Reg lualibs[] = {
  {"", luaopen_base},
  {LUA_LOADLIBNAME, luaopen_package},
  {LUA_TABLIBNAME, luaopen_table},
  {LUA_STRLIBNAME, luaopen_string},
  {LUA_MATHLIBNAME, luaopen_math},
  {LUA_DBLIBNAME, luaopen_debug},
  {NULL, NULL}
};

LUALIB_API void my_openlibs (lua_State *L) {
  const luaL_Reg *lib = lualibs;
  for (; lib->func; lib++) {
    lua_pushcfunction(L, lib->func);
    lua_pushstring(L, lib->name);
    lua_call(L, 1, 0);
  }
}

相关问题