嵌入式Lua - 超时流氓脚本(例如无限循环) - 任何人的例子?

时间:2011-02-27 16:17:55

标签: c++ lua

我在一个C ++应用程序中嵌入了Lua。我需要能够从滥用资源中杀死流氓(即写得很糟糕的脚本)。

我知道我无法满足导致脚本无限期运行的各种条件,所以现在,我只关注简单的Lua方面(即脚本方问题)。

我也知道这个问题(在各种形式下)已经在SO上提出。可能之所以经常被重新询问的原因是,到目前为止,没有人提供过几行代码来说明超时(对于像我上面描述的那样的简单情况)如何实际可以在工作代码中实现 - 而不是谈论一般性,关于如何实施。

如果有人在带有嵌入式Lua应用程序的C ++中实际实现了这种类型的功能,我(以及许多其他人 - 我敢肯定),将非常感谢一个显示的小片段:

  • 如何在运行Lua脚本之前设置超时(在C ++端)
  • 如何引发超时事件/错误(C ++ / Lua?)
  • 如何处理错误事件/异常(C ++端)

这样的片段(甚至伪代码)非常非常有用

3 个答案:

答案 0 :(得分:8)

您需要结合使用各种技术来解决这个问题。首先,您需要为不受信任的脚本建立一个合适的沙箱,其环境只提供安全且需要的全局变量和函数。其次,您需要提供内存和CPU使用的限制。第三,您需要明确拒绝从不受信任的来源加载预编译的字节码。

第一点很容易解决。在Lua用户wiki,邮件列表和SO上都有大量关于沙盒Lua的讨论。如果您意识到某些脚本比其他脚本更受信任,那么您几乎肯定已经在做这部分了。

第二点是你要问的问题。我马上回过头来看看。

第三点已经在邮件列表中讨论过了,但在其他媒体上可能没有很清楚。事实证明,Lua核心中存在许多难以或无法解决的漏洞,但这些漏洞依赖于“不正确”的字节码来运行。也就是说,它们不能从Lua源代码中运用,只能从预编译和仔细修补的字节代码中运用。编写一个拒绝加载任何二进制字节码的加载器是很简单的。

有了这些点,就可以通过CPU消耗,内存消耗或两者来解决拒绝服务攻击的问题。首先,坏消息。没有完美的技术可以防止这种情况发生。也就是说,最可靠的方法之一是将Lua解释器推入一个单独的进程,并使用平台的安全和配额功能来限制该进程的功能。在最坏的情况下,可以杀死失控过程,而不会对主应用程序造成任何伤害。最新版本的Firefox使用这种技术来包含插件中的错误的副作用,因此它不一定像听起来那么疯狂。

一个有趣的完整示例是Lua Live Demo。这是一个网页,您可以在其中输入Lua示例代码,在服务器上执行它,并查看结果。由于脚本可以从任何地方匿名输入,因此它们显然是不可信的。此Web应用程序似乎与可以要求的一样安全。它的源代码包是来自Lua的一位作者的available for download

答案 1 :(得分:1)

Snippet不能正确使用这个功能的实现所需的术语,这就是为什么你没有看到它。您可以使用调试挂钩在执行Lua代码期间提供回调。但是,在超时后中断该过程并非易事,并且取决于您的特定体系结构。

longjmp中捕获超时之后,您可以考虑在lua_call或lua_pcall之前使用luaHook设置跳转缓冲区。然后关闭Lua上下文并处理异常。超时可以通过多种方式实现,您可能已经考虑过项目中其他地方使用的内容。

完成此任务的最佳方法是在单独的进程中运行解释器。然后使用提供的操作系统工具来控制子进程。有关该方法的更多信息,请参阅RBerteig's excellent answer

答案 2 :(得分:1)

这是一个非常天真和简单,但无所不能的方法,

-- Limit may be in the millions range depending on your needs
setfenv(code,sandbox)
pcall (function() debug.sethook(
  function() error ("Timeout!") end,"", limit)
  code() 
  debug.sethook() 
  end);

我希望您可以通过C API实现相同目标。

然而,此方法存在很多问题。将限制设置得太低,它无法完成其工作。太高了,它并没有真正有效。 (块可以重复运行吗?)允许代码调用阻塞大量时间的函数,上面的内容毫无意义。允许它执行任何类型的pcall,它可以自己捕获错误。还有其他任何我还没有想过的问题。在这里,我也忽略了针对任何事情使用调试库的警告(除了调试之外)。

因此,如果您希望它可靠,您应该使用RB的解决方案。

我希望它能够很好地对抗偶然的无限循环,这种情况开始于lua程序员如此喜欢:P

对于内存过度使用,您可以使用函数检查 collectgarbage(“count”)以更小的间隔增加;你必须合并它们才能得到它们。