2010-08-09 10 views
6

से अपने स्वयं के पर्यावरण में एक अविश्वसनीय लुआ फ़ाइल को निष्पादित करने के लिए कैसे करें lua_setfenv() पर कॉल करके मैं अपने पर्यावरण में एक अविश्वसनीय .lua फ़ाइल निष्पादित करना चाहता हूं ताकि यह मेरे किसी भी कोड को प्रभावित न कर सके।सी एपीआई

उस फ़ंक्शन के लिए प्रलेखन हालांकि केवल फ़ंक्शन को कॉल करने का तरीका बताता है, फ़ाइल को निष्पादित करने के तरीके के बारे में नहीं।

वर्तमान फ़ाइल को चलाने के मैं का उपयोग करें:

int error = luaL_loadfile(mState, path.c_str()) || lua_pcall(mState, 0, 0, 0); 

मैं lua_setfenv साथ सी एपीआई से "dofile" lua समारोह कॉल करने के लिए है, या वहाँ यह करने के लिए एक और अधिक सुरुचिपूर्ण तरीका है?

उत्तर

9

sandboxing के लुआ उपयोगकर्ता की विकी में चर्चा देखें और script security के अधिक सामान्य विषय पर चर्चा देखें। इस तरह की चीज के साथ कई सूक्ष्म और इतने सूक्ष्म मुद्दे नहीं हैं। यह किया जा सकता है, लेकिन for i=1,1e39 do end जैसे कोड के खिलाफ सुरक्षा के लिए केवल सैंडबॉक्स में कौन से फ़ंक्शन उपलब्ध हैं, प्रतिबंधित करने की आवश्यकता है।

सामान्य तकनीक उस सैंडबॉक्स के लिए एक फ़ंक्शन वातावरण बनाना है जिसमें इसमें अनुमत कार्यों की श्वेतसूची है। कुछ मामलों में, यह सूची खाली भी हो सकती है, लेकिन उपयोगकर्ता को pairs() तक पहुंचने दें, उदाहरण के लिए, लगभग निश्चित रूप से हानिरहित है। सैंडबॉक्स पृष्ठ में ऐसी श्वेतसूची बनाने के लिए एक आसान संदर्भ के रूप में उनकी सुरक्षा द्वारा विभाजित सिस्टम कार्यों की एक सूची है।

फिर आप lua_setfenv() का उपयोग lua_loadfile() या lua_loadstring() के रूप में उपयुक्त के साथ उपयोगकर्ता के स्क्रिप्ट जो आप भरी हुई है (लेकिन अभी तक निष्पादित नहीं किया है) करने के लिए समारोह वातावरण लागू करने के लिए। पर्यावरण संलग्न होने के साथ, आप lua_pcall() और दोस्तों के साथ इसे निष्पादित कर सकते हैं। निष्पादन से पहले, कुछ लोगों ने वास्तव में उन परिचालनों के लिए लोड किए गए बाइटकोड को स्कैन किया है जिन्हें वे अनुमति नहीं देना चाहते हैं। इसका उपयोग पूरी तरह से लूप को रोकने या वैश्विक चरों को लिखने के लिए किया जा सकता है।

एक अन्य नोट यह है कि लोड फ़ंक्शंस आमतौर पर प्रीकंपिल्ड बाइटकोड या लुआ टेक्स्ट लोड करेंगे। यदि आप वीएम दुर्व्यवहार की पहचान करने के कई तरीकों की पहचान नहीं कर चुके हैं, तो यह अमान्य बाइटकोड हैंडक्रैफ्टिंग पर निर्भर करता है, तो यह बहुत सुरक्षित हो जाता है। चूंकि बाइटकोड फाइलें एक अच्छी तरह से परिभाषित बाइट अनुक्रम से शुरू होती हैं जो सादा ASCII पाठ नहीं है, आपको केवल स्क्रिप्ट बफर में स्क्रिप्ट पढ़ना है, मार्कर की अनुपस्थिति के लिए परीक्षण करना है, और केवल इसे lua_loadstring() पर पास करना है यदि यह नहीं है बाईटकोड।

इस तरह की चीज़ों के वर्षों में Lua-L mailing list पर एक उचित चर्चा हुई है, इसलिए वहां खोज करने में भी मददगार होने की संभावना है।

+0

धन्यवाद; मैंने डीबग हुक सेट करके अनंत लूप का ख्याल रखा है जो 10 मिलियन निर्देशों के बाद स्क्रिप्ट को समाप्त करता है। कार्यों के लिए, उपयोगकर्ता द्वारा प्रदान की गई फ़ाइल में केवल वैश्विक चर शामिल हैं और कोई भी कार्य नहीं है, इसलिए मुझे किसी भी फ़ंक्शन को श्वेतसूची में नहीं करना है। –

2

luaL_loadfile() खंड लोड करेगा, फिर पर्यावरण तालिका सेट करने के लिए lua_setfenv() पर कॉल करें, फिर खंड को निष्पादित करने के लिए lua_pcall() पर कॉल करें। न्यायाधीश मेगार्डन द्वारा Calling lua functions from .lua's using handles?

5

वैसे, इस मैं क्या कर समाप्त हो गया है:

/* Loads, compiles and executes an unstrusted file. */ 
bool Lua::RunUntrustedFile(const string& path) 
{ 
    if(luaL_loadfile(mState, path.c_str())) 
    { 
     ErrorLog(lua_tostring(mState, 1)); 
     Pop(1); 
     return false; 
    } 

    Lua::SetMaximumInstructions(100000000); 
    lua_newtable(mState); 
    lua_setglobal(mState, "upload"); 
    ASSERT(Lua::GetStackSize() == 1); 
    lua_getglobal(mState, "upload"); 
    ASSERT_ALWAYS(lua_setfenv(mState, 1) != 0); 
    ASSERT(Lua::GetStackSize() == 1); 

    if(lua_pcall(mState, 0, 0, 0)) 
    { 
     Lua::ClearMaximumInstructions(); 
     ErrorLog(lua_tostring(mState, -1)); 
     Pop(1); 
     return false; 
    } 

    ASSERT(Lua::GetStackSize() == 0); 
    Lua::ClearMaximumInstructions(); 

    return true; 
} 

"समर्थन" कार्य:

static void Pop(int elements = 1) { lua_pop(mState, elements); } 

/* Sets a maximum number of instructions before throwing an error */ 
static void SetMaximumInstructions(int count) { 
    lua_sethook(mState, &Lua::MaximumInstructionsReached, LUA_MASKCOUNT, count); 
} 
static void ClearMaximumInstructions() { 
    lua_sethook(mState, &Lua::MaximumInstructionsReached, 0, 0); 
} 

static void MaximumInstructionsReached(lua_State *, lua_Debug *) 
{ 
    Error("The maximum number of instructions has been reached"); 
} 

static int GetStackSize() { return lua_gettop(mState); } 
संबंधित मुद्दे