LuaL_openlibs() 和脚本沙箱化。

我正在将 Lua (5.1) 嵌入到一个 C/C++ 应用程序中。

我使用 LuaL_openlibs() 函数来加载基本库。但是,这个函数加载了一些其他的库,我想要禁用它们,让它们对我的 Lua 脚本不可用。

具体来说,我想要禁用 IO 和 OS 模块。是否有一个函数可以调用,以编程方式禁用 (或卸载) 这些模块,以便我可以创建一个安全的沙盒环境来运行 Lua 脚本?

原文链接 https://stackoverflow.com/questions/4551101

点赞
stackoverflow用户542629
stackoverflow用户542629

在早期版本的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

希望有所帮助。

2010-12-29 04:58:18
stackoverflow用户61761
stackoverflow用户61761

我不知道如何禁用模块,但是你仍然可以选择加载哪些模块,而不是全部加载。Lua 5.1 手册中的第 7.3 节 说:

luaopen_* 函数(打开库函数)不能像普通的 C 函数一样直接调用,必须通过 Lua 调用,就像调用 Lua 函数一样。

也就是说,在 Lua 5.0 中,你可以直接调用函数,如下:

luaopen_table(L);

... 但在 Lua 5.1 中,你需要将它作为 C 函数压入堆栈并使用 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
2010-12-29 07:02:49
stackoverflow用户501459
stackoverflow用户501459

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);
  }
}
2010-12-29 08:21:30
stackoverflow用户513763
stackoverflow用户513763

所有解决方案中最简单的一个:只需在加载库后执行 io=nil;os=nil

2010-12-29 09:37:30
stackoverflow用户264751
stackoverflow用户264751

重申我的回答另一个问题

自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 );

另请参见手册

2019-07-24 19:54:45