Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execution time limit for a Lua script called from the C API

Tags:

c++

c

lua

lua-api

luaL_loadfile(mState, path.c_str());
lua_pcall(mState, 0, 0, 0);

Is there a way to put an execution time limit (say 10-20 seconds) for those two C++ statements, that load and then execute a lua file?

Since the Lua file is untrusted I don't want a malicious user to hang the program indefinitely with an infinite loop in the Lua code.

Tagging C because the Lua API is C, tagging C++ because I'm using C++

like image 835
Thomas Bonini Avatar asked Aug 03 '10 21:08

Thomas Bonini


People also ask

What is Lua C API?

The C API is the set of functions that allow C code to interact with Lua. It comprises functions to read and write Lua global variables, to call Lua functions, to run pieces of Lua code, to register C functions so that they can later be called by Lua code, and so on.

Is Lua an API?

Lua has a simple and well documented API that allows strong integration with code written in other languages. It is easy to extend Lua with libraries written in other languages. It is also easy to extend programs written in other languages with Lua.

How do I run a Lua script?

To run a Lua scriptOpen the Lua Script Library through Prepare > Run Lua Script. Use the appearing dialog to load, save, and execute Lua scripts as well as to create new ones. Select the script to be run. Click Execute Script.


1 Answers

There's lua_sethook which can be used to tell the interpreter to call a hook after every 'count' instructions executed. This way you can monitor the user script and terminate it if it eats up its quota:

 int lua_sethook (lua_State *L, lua_Hook f, int mask, int count);

This can also be used from Lua:

debug.sethook(function() print("That's enough for today"); os.exit(0); end, "", 10000)
for i=1,10000 do end

If you use the techniques from http://lua-users.org/wiki/SandBoxes then you can set up a safe execution environment with sethook() and friends entirely from Lua and then switch to sandbox mode while executing the user script. I've tried that here, just for you to get started:

-- set an execution quota 
local function set_quota(secs)
 local st=os.clock()
 function check() 
  if os.clock()-st > secs then 
    debug.sethook() -- disable hooks
    error("quota exceeded")
  end
 end
 debug.sethook(check,"",100000);
end

-- these are the global objects, the user can use:
local env = {print=print}

-- The user code is allowed to run for 5 seconds.
set_quota(5)

-- run code under environment:
local function run(untrusted_code)
  local untrusted_function, message = loadstring(untrusted_code)
  if not untrusted_function then return nil, message end
  setfenv(untrusted_function, env)
  return pcall(untrusted_function)
end

-- here is the user code:
local userscript=[[
function fib(n) 
 if n<2 then return n
 else return fib(n-2)+fib(n-1)
 end
end
for n=1,42 do print(n,fib(n)) end
]]
-- call it:
local r,m=run(userscript)
print(r,m)

This should print values of fib() for 5 seconds and then show an error.

like image 127
Nordic Mainframe Avatar answered Oct 11 '22 01:10

Nordic Mainframe