/usr/share/lua/5.1/supple/sandbox.lua is in lua-supple 1.0.8-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | -- lib/supple/sandbox.lua
--
-- Sandbox (for) Untrusted Procedure Partitioning (in) Lua Engine
--
-- Code which runs the core sandbox functionality of supple.
--
-- This module runs in the sandbox interpreter which means some of the code
-- runs with root access. As such, we minimise what can be done before
-- we drop privileges.
--
-- The wrapper used to run us already ensured that LUA_PATH etc are
-- not set, so we don't have to worry about non-system-installed modules
-- getting in our way. Once the supple libraries are loaded (which will
-- include loading luxio etc) we're good to go and can ask the supple.capi
-- module to lock us down.
--
-- Copyright 2012 Daniel Silverstone <dsilvers@digital-scurf.org>
--
-- For licence terms, see COPYING
--
--- Running code in sandboxes
--
-- This module is used by the sandbox code itself to start running sandboxed
-- Lua. The only entry point is invoked by the sandbox C wrapper during
-- startup. From here the sandbox locks itself down and then begins to listen
-- for work to do.
--
-- You should only need to interact with this module if you are writing your
-- own Supple wrapper binary to use instead of the provided wrapper.
--
local capi = require 'supple.capi'
local objects = require 'supple.objects'
local comms = require 'supple.comms'
local luxio = require 'luxio'
local sio = require 'luxio.simple'
local track = require 'supple.track'
local loadstring = loadstring
local load = load
local setfenv = setfenv
local gc = collectgarbage
local unpack = unpack
local xpcall = xpcall
local traceback = debug.traceback
local function set_limits(ltab)
local count = ltab.count
local memory = ltab.memory
local limits = { count = count, memory = memory}
if limits.memory then
-- Bump memory limit by current usage to be kinder
limits.memory = limits.memory + (gc "count")
end
if not limits.count and not limits.memory then
return false, "Expected an opcode count or total memory limit"
end
comms.set_limits(limits)
return true
end
local function _wrap(fn, src, globs, dont_wrap_globs)
local fn_ret, msg
if not dont_wrap_globs then
globs = setmetatable({}, { __index = globs, __metatable = true })
end
assert(fn, "No function/source provided?")
assert(src, "No source name provided?")
if setfenv then
-- Lua 5.1 style load...
fn_ret, msg = ((capi.rawtype(fn) == "string") and loadstring or load)(fn, src)
if not fn_ret then
return nil, msg
end
setfenv(fn_ret, globs)
else
-- Lua 5.2 style load...
fn_ret, msg = load(fn, src, "t", globs)
if not fn_ret then
return nil, msg
end
end
assert(fn_ret, "Unusual, missing fn_ret now?")
return fn_ret, globs
end
local function wrapped_unpack(t)
local packed = t
if capi.rawtype(t) ~= "table" then
local len = #t
packed = {}
for i = 1, len do
packed[i] = t[i]
end
end
return unpack(packed)
end
--- Start the sandbox running
--
-- This routine is invoked by the sandbox wrapper C code and starts the sandbox
-- running. Approximately it locks the sandbox down, including various limits
-- such as chroot, rlimits, dropping privileges, and seccomp mode if available.
-- Then it begins the main RPC loop for the sandbox.
--
-- @function run
local function run()
-- Run the sandbox
local result, errno = capi.lockdown()
if result ~= "ok" and result ~= "OK"
-- START_TEST_ONLY
and result ~= "oknonroot"
-- END_TEST_ONLY
then
-- Failure to sandbox, so abort
print(result, luxio.strerror(errno))
return errno
end
if result == "ok" then
-- Note, if result is "OK" then we're pretty hard jailed
-- and cannot even do this test lest we get killed
-- Check that we're definitely solidly jailed
fh, errno = sio.open("testfile", "rw")
if fh then
fh:close()
luxio.unlink("testfile")
return 1
end
end
-- Prepare a severely limited sandbox
local sandbox_globals = {
type = capi.type,
pairs = capi.pairs,
ipairs = capi.ipairs,
next = capi.next,
unpack = wrapped_unpack,
}
for _, k in ipairs({ "table", "string", "pcall",
"xpcall", "tostring", "tonumber", "math",
"coroutine", "select", "error", "assert" }) do
sandbox_globals[k] = _G[k]
end
-- Complete its "globals"
sandbox_globals._G = sandbox_globals
local _go_str = [[
return ({...})[1]()
]]
local fn, globs = _wrap(_go_str, "sandbox", sandbox_globals)
if not fn then
return 1
end
objects.set_name(("supple-sandbox[%d,%%d]"):format(luxio.getpid()))
objects.set_proc_call(comms.call)
local dont_wrap_globs = true
local function wrappered_load(str, name)
local dwg = dont_wrap_globs
dont_wrap_globs = false
return _wrap(str, name, sandbox_globals, dwg)
end
-- Pretend we've "given" the host an object called 'supple:loadstring'
-- which is the loadstring/load function
track.start()
objects.give(set_limits, "supple:set_limits")
objects.give(wrappered_load, "supple:loadstring")
objects.give(objects.clean_down, "supple:clean_down")
comms._set_fd(0)
return fn(comms._wait)
end
local function wrapper_run()
local ok, retcode = xpcall(run, traceback)
if not ok then
error(retcode)
end
return retcode
end
return {
run = wrapper_run,
}
|