Skip to content

Commit 0613d87

Browse files
Enable Lua packages and Lua C packages
The 'require' function is enabled to load Lua and Lua C packages/modules. package.loaded and package.seeall have also been reactivated. Pure Lua modules must be placed correctly in either: <resource>/?.lua <resource>/?/init.lua Lua C Modules must be placed in: /server/mods/deathmatch/modules/?.dll To easily test or use modules for Windows: Download and install Lua for Windows. Copy contents of C:\Program Files (x86)\Lua\5.1\clibs into /server/mods/deathmatch/modules. Use e.g. require"lfs" Considerations: 1) vulnerable to debug library (debug.getregistry) 2) no ACL implementation
1 parent c52a459 commit 0613d87

File tree

3 files changed

+88
-10
lines changed

3 files changed

+88
-10
lines changed

Server/mods/deathmatch/logic/lua/CLuaMain.cpp

Lines changed: 80 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ CLuaMain::CLuaMain ( CLuaManager* pLuaManager,
6363

6464
m_bEnableOOP = bEnableOOP;
6565

66+
m_iPackageRef = -1;
6667

6768
CPerfStatLuaMemory::GetSingleton ()->OnLuaMainCreate ( this );
6869
CPerfStatLuaTiming::GetSingleton ()->OnLuaMainCreate ( this );
@@ -126,13 +127,33 @@ void CLuaMain::InitSecurity ( void )
126127
{
127128
lua_register ( m_luaVM, "dofile", CLuaUtilDefs::DisabledFunction );
128129
lua_register ( m_luaVM, "loadfile", CLuaUtilDefs::DisabledFunction );
129-
lua_register ( m_luaVM, "require", CLuaUtilDefs::DisabledFunction );
130-
lua_register ( m_luaVM, "loadlib", CLuaUtilDefs::DisabledFunction );
131130
lua_register ( m_luaVM, "getfenv", CLuaUtilDefs::DisabledFunction );
132131
lua_register ( m_luaVM, "newproxy", CLuaUtilDefs::DisabledFunction );
133132
}
134133

135134

135+
void CLuaMain::InitPackageSecurity(void)
136+
{
137+
// Grab our original package library
138+
lua_getglobal(m_luaVM, "package"); // stack: [tbl_package]
139+
140+
// Create a new package library, with only whitelisted functions
141+
lua_newtable(m_luaVM); // stack: [tbl_package,tbl_new]
142+
std::vector<const char*> szWhitelist = { "loaded", "seeall" };
143+
for (auto it = szWhitelist.begin(); it != szWhitelist.end(); it++)
144+
{
145+
lua_pushstring(m_luaVM, *it); // stack: [tbl_package,tbl_new,"loaded"]
146+
lua_pushstring(m_luaVM, *it); // stack: [tbl_package,tbl_new,"loaded","loaded"]
147+
lua_gettable(m_luaVM, -4); // stack: [tbl_package,tbl_new,"loaded",package.loaded]
148+
lua_settable(m_luaVM, -3); // stack: [tbl_package,tbl_new]
149+
}
150+
lua_setglobal(m_luaVM, "package"); // stack: [tbl_package]
151+
152+
// Keep the original package library safe in the registry
153+
m_iPackageRef = luaL_ref(m_luaVM, LUA_REGISTRYINDEX); // stack: []
154+
}
155+
156+
136157
void CLuaMain::InitClasses ( lua_State* luaVM )
137158
{
138159
lua_initclasses ( luaVM );
@@ -185,13 +206,27 @@ void CLuaMain::InitVM ( void )
185206
lua_sethook ( m_luaVM, InstructionCountHook, LUA_MASKCOUNT, HOOK_INSTRUCTION_COUNT );
186207

187208
// Load LUA libraries
188-
luaopen_base ( m_luaVM );
189-
luaopen_math ( m_luaVM );
190-
luaopen_string ( m_luaVM );
191-
luaopen_table ( m_luaVM );
192-
luaopen_debug ( m_luaVM );
193-
luaopen_utf8 ( m_luaVM );
194-
209+
const luaL_Reg lualibs[] = {
210+
{ "", luaopen_base },
211+
{ LUA_LOADLIBNAME, luaopen_package },
212+
{ LUA_TABLIBNAME, luaopen_table },
213+
{ LUA_STRLIBNAME, luaopen_string },
214+
{ LUA_MATHLIBNAME, luaopen_math },
215+
{ LUA_DBLIBNAME, luaopen_debug },
216+
{ "utf8", luaopen_utf8 },
217+
{ NULL, NULL }
218+
};
219+
220+
const luaL_Reg *lib = lualibs;
221+
for (; lib->func; lib++) {
222+
lua_pushcfunction(m_luaVM, lib->func);
223+
lua_pushstring(m_luaVM, lib->name);
224+
lua_call(m_luaVM, 1, 0);
225+
}
226+
227+
// Initialize our customized 'package' library with restricted functions
228+
InitPackageSecurity ();
229+
195230
// Initialize security restrictions. Very important to prevent lua trojans and viruses!
196231
InitSecurity ();
197232

@@ -686,3 +721,39 @@ int CLuaMain::OnUndump( const char* p, size_t n )
686721
}
687722
return 1;
688723
}
724+
725+
726+
///////////////////////////////////////////////////////////////
727+
//
728+
// CLuaMain::SetPackagePaths
729+
//
730+
// Sets module directories for pure lua and C lua modules
731+
//
732+
///////////////////////////////////////////////////////////////
733+
bool CLuaMain::SetPackagePaths(SString strPath, SString strCPath)
734+
{
735+
if (!m_luaVM || m_iPackageRef < 0 )
736+
return false;
737+
738+
// Setup our wildcards for searching
739+
strPath = PathJoin(strPath, "?.lua") + ";" + PathJoin(strPath, "?/init.lua");
740+
741+
#ifdef WIN32
742+
strCPath = PathJoin(strCPath, "?.dll");
743+
#else
744+
strCPath = PathJoin(strCPath, "?.so");
745+
#endif
746+
747+
// Overwrite our path variable function from the registry (saved earlier)
748+
lua_rawgeti(m_luaVM, LUA_REGISTRYINDEX, m_iPackageRef); // stack: [tbl_hiddenPackage]
749+
lua_pushstring(m_luaVM, "path"); // stack: [tbl_hiddenPackage,"path"]
750+
lua_pushstring(m_luaVM, strPath.c_str()); // stack: [tbl_hiddenPackage,"path","C:/someresource/?.lua"]
751+
lua_settable(m_luaVM, -3); // stack: [tbl_hiddenPackage]
752+
753+
lua_pushstring(m_luaVM, "cpath"); // stack: [tbl_hiddenPackage,"cpath"]
754+
lua_pushstring(m_luaVM, strCPath.c_str()); // stack: [tbl_hiddenPackage,"cpath","C:/somemodules/?.dll"]
755+
lua_settable(m_luaVM, -3); // stack: [tbl_hiddenPackage]
756+
lua_pop(m_luaVM, -1); // stack: []
757+
758+
return true;
759+
}

Server/mods/deathmatch/logic/lua/CLuaMain.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,11 @@ class CLuaMain //: public CClient
120120
static int LuaLoadBuffer ( lua_State *L, const char *buff, size_t sz, const char *name );
121121
static int OnUndump ( const char* p, size_t n );
122122

123+
bool SetPackagePaths ( SString strPath, SString strCPath );
124+
123125
private:
124126
void InitSecurity ( void );
127+
void InitPackageSecurity ( void );
125128
void InitClasses ( lua_State* luaVM );
126129

127130
public:
@@ -134,6 +137,7 @@ class CLuaMain //: public CClient
134137
SString m_strScriptName;
135138

136139
lua_State* m_luaVM;
140+
int m_iPackageRef;
137141
CLuaTimerManager* m_pLuaTimerManager;
138142

139143
class CResource* m_pResource;

Server/mods/deathmatch/logic/lua/CLuaManager.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,10 @@ CLuaMain * CLuaManager::CreateVirtualMachine ( CResource* pResourceOwner, bool b
7676
CLuaMain * pLuaMain = new CLuaMain ( this, m_pObjectManager, m_pPlayerManager, m_pVehicleManager, m_pBlipManager, m_pRadarAreaManager, m_pMapManager, pResourceOwner, bEnableOOP );
7777
m_virtualMachines.push_back ( pLuaMain );
7878
pLuaMain->InitVM ();
79-
79+
pLuaMain->SetPackagePaths(
80+
pResourceOwner->IsResourceZip() ? pResourceOwner->GetResourceCacheDirectoryPath() : pResourceOwner->GetResourceDirectoryPath(),
81+
PathJoin(g_pServerInterface->GetModManager()->GetServerPath(), SERVER_BIN_PATH_MOD, "modules")
82+
);
8083
m_pLuaModuleManager->RegisterFunctions ( pLuaMain->GetVirtualMachine() );
8184

8285
return pLuaMain;

0 commit comments

Comments
 (0)