lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


There's a fundamental difference even if the effect looks the same: the loop is not supposed to leak memory, but nothing is garbage collected. and most CPU time will be used by the garbage collector trying to finalize more and more objects without success, not in the Lua program itself but within the Lua virtual machine itself becoming completely out of control and probably crashing even before it can use the panic function.

This should not occur if there was a way to set safe limits to the allocations a "thread" (in fact just a coroutine) can do: only the single thread would run out of limit, would be affected by error() or nil objects being allocated to them, the other threads would run unaffected. No panic event would occur. And a parent thread could detect these situations, and terminate only that offending thread and could take other preventive measures (by being able to detect the origin of this thread).

This is something needed for Lua programs that run threads to implement a web service, or simply to be able (like in _javascript_) to use Lua as an hypervisor to virtualize a complete OS: there's a need to be able to track and restrict resource usages in each thread (this is also needed to protect against Meltdown-like time-based attacks targetting the Lua's allocator or garbage collector whose execution time becomes extremely high and thus easily exploitable to create very effective "spying" side-channels).


Le mer. 28 nov. 2018 à 02:37, Tim Hill <drtimhill@gmail.com> a écrit :

> On Nov 27, 2018, at 4:12 PM, Philippe Verdy <verdy_p@wanadoo.fr> wrote:
>
> This example is "blocking" all threads, but does not use recursion or reentrance.
>
>
>   while true do
>     local x={}
>     setmetatable(x, mt)
>   end
>
> It will allocate an infinite number of new objects that will never be finalized. This thread will exhaust rapidly all resources allowed by the OS for the process, possibly allocating gigabytes or more that will never be used and will constantly grow the finalization list. The CPU will be running at 100%, with lot of paging to disk, causing severe problems to the host OS if the Lua host process is not given hard limits using the OS API (if not, the OS will finally hang and probably crash: this gives then a successful DOS attack). But if we can force a __gc to not finalize the object immediately by putting it in a "delay" list that will be marked as noit finalizable and will remain reachable, we can limit the frequency for finalization of these objects.

  t = {}
   while true do
       table.insert(t, “foo”)
   end

So does this code. So do any number of similar run-away blocks of code. What is so special about your example that it should be prevented, when simple examples like mine can do the same thing?

—Tim