Class: ExecSandbox::Sandbox
- Inherits:
-
Object
- Object
- ExecSandbox::Sandbox
- Defined in:
- lib/exec_sandbox/sandbox.rb
Overview
Manages sandboxed processes.
Instance Attribute Summary collapse
-
#path ⇒ Object
readonly
The path to the sandbox’s working directory.
-
#user_name ⇒ Object
readonly
The un-privileged user that execs sandboxed binaries.
Class Method Summary collapse
-
.cleanup ⇒ Array<String>
Removes temporary users created by old sandboxes.
Instance Method Summary collapse
-
#close ⇒ Object
Removes the files and temporary user associated with this sandbox.
-
#finalize ⇒ Object
Cleans up when the sandbox object is garbage-collected.
-
#initialize(admin) ⇒ Sandbox
constructor
Empty sandbox.
-
#pull(from, to) ⇒ String
Copies a file or directory from the sandbox.
-
#push(from, options = {}) ⇒ String
Copies a file or directory to the sandbox.
-
#run(command, options = {}) ⇒ Hash
Runs a command in the sandbox.
Constructor Details
#initialize(admin) ⇒ Sandbox
Empty sandbox.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/exec_sandbox/sandbox.rb', line 16 def initialize(admin) @user_name = ExecSandbox::Users.temp user_pwd = Etc.getpwnam @user_name @user_uid = user_pwd.uid @user_gid = user_pwd.gid @path = user_pwd.dir @admin_name = admin admin_pwd = Etc.getpwnam(@admin_name) @admin_uid = admin_pwd.uid @admin_gid = admin_pwd.gid @destroyed = false # principal argument for Spawn.spawn() @principal = { uid: @user_uid, gid: @user_gid, dir: @path } end |
Instance Attribute Details
#path ⇒ Object (readonly)
The path to the sandbox’s working directory.
7 8 9 |
# File 'lib/exec_sandbox/sandbox.rb', line 7 def path @path end |
#user_name ⇒ Object (readonly)
The un-privileged user that execs sandboxed binaries.
10 11 12 |
# File 'lib/exec_sandbox/sandbox.rb', line 10 def user_name @user_name end |
Class Method Details
.cleanup ⇒ Array<String>
Removes temporary users created by old sandboxes.
Sandboxes usually clean up after themselves. For the rare circumstances where that doesn’t happen (VM crash, Ctrl+C, SIGKILL), this method finds and cleans up the temporary users created for sandboxing.
166 167 168 |
# File 'lib/exec_sandbox/sandbox.rb', line 166 def self.cleanup Users.destroy_temps end |
Instance Method Details
#close ⇒ Object
Removes the files and temporary user associated with this sandbox.
148 149 150 151 152 |
# File 'lib/exec_sandbox/sandbox.rb', line 148 def close return if @destroyed ExecSandbox::Users.destroy @user_name @destroyed = true end |
#finalize ⇒ Object
Cleans up when the sandbox object is garbage-collected.
155 156 157 |
# File 'lib/exec_sandbox/sandbox.rb', line 155 def finalize close end |
#pull(from, to) ⇒ String
Copies a file or directory from the sandbox.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/exec_sandbox/sandbox.rb', line 66 def pull(from, to) from = File.join @path, from return nil unless File.exist? from FileUtils.cp_r from, to FileUtils.chmod_R 0770, to FileUtils.chown_R @admin_uid, @admin_gid, to # NOTE: making a file / directory read-only is useless -- the sandboxed # process can replace the file with another copy of the file; this can # be worked around by noting the inode number of the protected file / # dir, and making a hard link to it somewhere else so the inode won't # be reused. to end |
#push(from, options = {}) ⇒ String
Copies a file or directory to the sandbox.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/exec_sandbox/sandbox.rb', line 42 def push(from, = {}) to = File.join @path, ([:to] || File.basename(from)) FileUtils.cp_r from, to = [:read_only] ? 0770 : 0750 FileUtils.chmod_R , to FileUtils.chown_R @admin_uid, @user_gid, to # NOTE: making a file / directory read-only is useless -- the sandboxed # process can replace the file with another copy of the file; this can # be worked around by noting the inode number of the protected file / # dir, and making a hard link to it somewhere else so the inode won't # be reused. to end |
#run(command, options = {}) ⇒ Hash
Runs a command in the sandbox.
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 |
# File 'lib/exec_sandbox/sandbox.rb', line 100 def run(command, = {}) limits = [:limits] || {} io = {} if [:in] io[:in] = [:in] in_rd = nil else in_rd, in_wr = IO.pipe in_wr.write [:in_data] if [:in_data] in_wr.close io[:in] = in_rd end if [:out] io[:out] = [:out] else out_rd, out_wr = IO.pipe io[:out] = out_wr end case [:err] when :out io[:err] = STDOUT when :none # Don't set io[:err], so the child's stderr will be closed. else io[:err] = STDERR end pid = ExecSandbox::Spawn.spawn command, io, @principal, limits # Close the pipe ends that are meant to be used in the child. in_rd.close if in_rd out_wr.close if out_wr # Collect information about the child. if out_rd out_pieces = [] out_pieces << out_rd.read rescue nil end status = ExecSandbox::Wait4.wait4 pid if out_rd out_pieces << out_rd.read rescue nil out_rd.close status[:out_data] = out_pieces.join('') end status end |