File: sandbox.lua

package info (click to toggle)
wireplumber 0.5.12-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,244 kB
  • sloc: ansic: 41,043; python: 391; sh: 62; makefile: 57; xml: 23
file content (90 lines) | stat: -rw-r--r-- 2,869 bytes parent folder | download | duplicates (4)
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
-- WirePlumber
--
-- Copyright © 2020 Collabora Ltd.
--    @author George Kiagiadakis <george.kiagiadakis@collabora.com>
--
-- Based on https://github.com/kikito/sandbox.lua
-- Copyright © 2013 Enrique García Cota
--
-- SPDX-License-Identifier: MIT

local SANDBOX_CONFIG = ...
local SANDBOX_ENV = {}

function create_sandbox_env()
  local function populate_env(id)
    local module, method = id:match('([^%.]+)%.([^%.]+)')
    if module then
      SANDBOX_ENV[module]         = SANDBOX_ENV[module] or {}
      SANDBOX_ENV[module][method] = _G[module][method]
    else
      SANDBOX_ENV[id] = _G[id]
    end
  end

  if not SANDBOX_ENV._VERSION then
    -- List of exported functions and packages
    ([[ _VERSION assert error ipairs   next pairs  tonumber
        pcall    select print tostring type xpcall require
        table    string math  package  utf8 debug  coroutine
        os.clock  os.difftime os.time  os.date     os.getenv
        setmetatable getmetatable
    ]]):gsub('%S+', populate_env)

    -- Additionally export everything in SANDBOX_EXPORT
    if type(SANDBOX_EXPORT) == "table" then
      for k, v in pairs(SANDBOX_EXPORT) do
        SANDBOX_ENV[k] = v
      end
    end

    -- Additionally protect packages from malicious scripts trying to override methods
    for k, v in pairs(SANDBOX_ENV) do
      if type(v) == "table" then
        SANDBOX_ENV[k] = setmetatable({}, {
          __index = v,
          __call = function(t, ...)
            return t["__new"](...)
          end,
          __newindex = function(_, attr_name, _)
            error('Can not modify ' .. k .. '.' .. attr_name .. '. Protected by the sandbox.')
          end
        })
      end
    end
  end

  -- chunk's environment will be an empty table with __index
  -- to access our SANDBOX_ENV (without being able to write it)
  return setmetatable({}, {
    __index = SANDBOX_ENV,
  })
end

if SANDBOX_CONFIG["isolate_env"] then
  -- in isolate_env mode, use a separate environment for each loaded chunk and
  -- store all of them in a global table so that they are not garbage collected
  SANDBOX_ENV_LIST = {}

  function sandbox(chunk, ...)
    local env = create_sandbox_env()
    -- store the chunk's environment so that it is not garbage collected
    table.insert(SANDBOX_ENV_LIST, env)
    -- set it as the chunk's 1st upvalue (__ENV)
    debug.setupvalue(chunk, 1, env)
    -- execute the chunk
    return chunk(...)
  end
else
  -- in common_env mode, use the same environment for all loaded chunks
  -- chunk's environment will be an empty table with __index
  -- to access our SANDBOX_ENV (without being able to write it)
  SANDBOX_COMMON_ENV = create_sandbox_env()

  function sandbox(chunk, ...)
    -- set it as the chunk's 1st upvalue (__ENV)
    debug.setupvalue(chunk, 1, SANDBOX_COMMON_ENV)
    -- execute the chunk
    return chunk(...)
  end
end