Interface

Simple example:

    local L = sandbox.new()
    L:stdin(io.stdin)
    L:stdout(io.stdout)
    L:stderr(io.stderr)
    L:env(os.getenv)
    L:dofile("script.lua")
    L:close()

Advanced example:

    local dev_null = sandbox.newstream()
    local incomm = sandbox.newstream(
      function ()
        local l = io.read()
	return l and l .. "\n"
      end)
    local outcomm = sandbox.newstream(nil,
      function (s)
        io.write(s)
      end)

    local L = sandbox.new()
    L:stdin(incomm)
    L:stdout(outcomm)
    L:stderr(dev_null)
    L:env({PATH="/bin:/usr/bin:.", LANG="en_US"})
    L:luaopen()
    L:dofile("script.lua")
    L:close()

Description

sandbox.new()

Create a new sandbox.

Packages opened in lua_State of sandbox:

:stdin(filehandle)
:stdout(filehandle)
:stderr(filehandle)

The stdin, stdout and stderr methods control stdin, stdout and stderr of sandbox, respective.

If filehandle parameter is nil, the default, when sandbox is running, the filehandle for sandbox will be similar a filehandle from /dev/null device of Unix. The return is nil.

If nothing is passed, the method doesn't modify the currency filehandle and return the current filehandle. If a filehandle, it is assing to respective filehandle of sandbox and return this.

The sandbox's print function is redefined to write to stdout assigned to sandbox and instead to the process' stdout, the Lua standard.

When code running in sandbox close one of these filehandles, it is virtualy closed, i.e. for sandbox the filehandle is closed, but out of sandbox is still opened.

:env(table)
:env(function)
:env(nil)

Define the enviroment what io.getenv from sandbox will use. The form :env(table) only indicate a table for io.getenv from sandbox consult.

The call :env(nil) has identical effect that :env({}), but is a little more cheap.

The form :env(function) is very flexible and useful. The function passed must accept a string as key, your unique parameter, and return the value associated with the key. The value must be a string or nil if the key doesn't exist.

:luaopen()

Open sandbox package in the lua_State from sandbox.

Unhappyly, currently, this operation is dangerous, therefore it allow a alloc all memory. The sandbox doesn't have a memory restriction yet.

In current version, the sandbox limit the depth of nested sandbox in 10. It protect the host against stack overflow attack by nesting sandboxs.

:dofile("script.lua")

Execute a file in sandbox. Note, the lua_State used is not a new lua_State, it is the same lua_State since sandbox.new call, always. This method may be called multiple times.

The side effects from call dofile method multiple times are responsability of developer.

:close()

Finish the sandbox. All associated resources are disposed.

sandbox.newstream(reader_function, writer_function, cleaner_function)

Create a fake stream, i.e. a filehandle that read from a function and write to other function. In other words, fake stream is a filter with stream interface.

Fake stream is very useful and generic, this functionality goes very beyond sandbox in itself, e.g. access, through stream interface, ftp, http, smtp, pop, imap, gzip etc. If somebody implements this, please let me know.

The reader_function receive the buffer size of caller as parameter. It parameter is just a good hint! The reader_function doesn't need return a string this size. The reader_function must return the data readed as string. The end of stream is signaled with nil or "". If the first return from reader_function isn't nil, a string or a number, the read operation from caller receive a read error!

The writer_function receive a string to write and return nothing.

The cleaner_function doesn't receive parameters. It is called when the fake stream handle's close method is called.

The functions reader_function, writer_function and cleaner_function may are ignored with nil or absentee. A fake stream only with reader_function just read, one only with writer_function just write.

Call sandbox.newstream without a reader_function AND a writer_function return a fake stream similar to one handle from /dev/null, but a little cheaper and more "portable" (the platform doesn't have to be Unix). This solution is as postable as the Sandbox library is.

The current code doesn't support reader_function and writer_function simultaneously! There is a good reason for this, please to refer to the source code. Basically, when reader and write aren't sincrozined, a segmentation fault error is raised.

This functionality use memory from lua_State associate to work and use memory out from lua_State associate to the C file handle. The memory out aren't worthless, normally bigger that 8kB!