1 --[==========================================================================[
2 sandbox.lua: Lua sandboxing facilities
3 --[==========================================================================[
4 Copyright (C) 2007 the VideoLAN team
7 Authors: Antoine Cellerier <dionoea at videolan dot org>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 --]==========================================================================]
24 module("sandbox",package.seeall)
26 -- See Programming in Lua (second edition) for sandbox examples
27 -- See http://lua-users.org/wiki/SandBoxes for a list of SAFE/UNSAFE variables
29 local sandbox_blacklist = {
30 collectgarbage = true,
35 load = true, -- Can be protected I guess
36 loadfile = true, -- Can be protected I guess
37 loadstring = true, -- Can be protected I guess
49 function readonly_table_proxy(name,src,blacklist)
50 if type(src)=="nil" then return end
51 if type(src)~="table" then error("2nd argument must be a table (or nil)") end
56 for _, v in pairs(blacklist) do
60 local metatable_readonly = {
61 __index = function(self,key)
63 error("Sandbox: Access to `"..name.."."..key.."' is forbidden.")
67 __newindex = function(self,key,value)
68 error("It is forbidden to modify elements of this table.")
71 return setmetatable({},metatable_readonly)
74 -- Of course, all of this is useless if the sandbox calling code has
75 -- another reference to one of these tables in his global environement.
76 local sandbox_proxy = {
77 coroutine = readonly_table_proxy("coroutine",coroutine),
78 string = readonly_table_proxy("string",string,{"dump"}),
79 table = readonly_table_proxy("table",table),
80 math = readonly_table_proxy("math",math),
81 io = readonly_table_proxy("io",io),
82 os = readonly_table_proxy("os",os,{"exit","getenv","remove",
83 "rename","setlocale"}),
84 sandbox = readonly_table_proxy("sandbox",sandbox),
87 function sandbox(func,override)
89 local override = override or {}
90 local sandbox_metatable =
92 __index = function(self,key)
96 if sandbox_blacklist[key] then
97 error( "Sandbox: Access to `"..key.."' is forbidden." )
99 --print(key,"not found in env. Looking in sandbox_proxy and _G")
100 local value = sandbox_proxy[key] or _G[key]
101 rawset(self,key,value) -- Keep a local copy
104 __newindex = function(self,key,value)
105 if override and override[key] then
106 error( "Sandbox: Variable `"..key.."' is read only." )
108 return rawset(self,key,value)
111 local sandbox_env = setmetatable({},sandbox_metatable)
113 setfenv(func,sandbox_env)
114 local ret = {func(...)} -- Not perfect (if func returns nil before
115 -- another return value) ... but it's better