[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: On implementing a functions whitelist for a sandbox
- From: Sean Conner <sean@...>
- Date: Tue, 6 Aug 2019 19:54:07 -0400
It was thus said that the Great Kynn Jones once stated:
> Hi!
>
> I am learning Lua by working my way through Programming in Lua (4th
> edition).
>
> In chapter 25 there's a discussion on implementing a sandbox, based on
> defining a "white list" (my wording) of allowable functions.
>
> This seems straightforward in principle, but in practice I am having a hard
> time getting hold of some core functions that *need* to go into the
> whitelist. The code below is a very pared-down example that shows one of
> these elusive functions in actions.
>
> #!/usr/bin/env lua5.3
> local loaded_chunk = assert(load('nonexistent()', "=(load)", "t", {}))
> local function callhook ()
> local info = debug.getinfo(2, "fnS")
> if info.func == loaded_chunk then return end
> error(string.format("calling disallowed function (%s:%d): %s (%s)",
> info.short_src,
> info.linedefined,
> (info.name or "?"),
> info.func))
> end
> debug.sethook(callhook, "c")
> loaded_chunk()
>
> If I run this script on my Debian system I get the following output:
>
> lua5.3: ./snippet.lua:6: calling disallowed function ([C]:-1):
> nonexistent (function: 0x55918f70aef0)
> stack traceback:
> [C]: in function 'error'
> ./snippet.lua:6: in function <./snippet.lua:3>
> [C]: in global 'nonexistent'
> (load):1: in local 'loaded_chunk'
> ./snippet.lua:13: in main chunk
> [C]: in ?
>
> Now, this output is somewhat disconcerting (to me at least, since it gives
> the impression that the true-to-its-name function `nonexistent` actually
> lives at 0x55918f70aef0), but the important thing is that what has
> triggered the call hook is a "mystery function X" called in response to the
> `attempt to call a nil value` error. It is this mystery function X that I
> want to include into the allowed functions whitelist.
>
> How can I determine this function and refer to it in my code?
Is the only purpose of getting this function [1] to satisfy the method you
are using to identify missing functions?
When I sandbox code, I know the list of functions I want the sandboxed
code to run, and only include those functions. If I want to give the
sandboxed code access to the functions print() and os.getenv(), I'll
explicitiely add them to the environment:
env = { print = print , os = { getenv = os.getenv } }
f = assert(loadfile(file,"t",env))
assert(pcall(f))
I modified your example a bit:
[spc]lucy:/tmp>lua
Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
> loaded_chunk = assert(load('nonexistent()',"=(load)","t",{}))
> assert(pcall(loaded_chunk))
stdin:1: (load):1: attempt to call a nil value (global 'nonexistent')
stack traceback:
[C]: in function 'assert'
stdin:1: in main chunk
[C]: in ?
>
-spc
[1] The function is an internal function written in C. It has no name
in Lua.