bwrap 1.0.0.pre.alpha5 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +26 -0
- data/lib/bwrap/args/args.rb +5 -1
- data/lib/bwrap/args/bind/library.rb +188 -0
- data/lib/bwrap/args/bind/mime.rb +58 -0
- data/lib/bwrap/args/bind.rb +27 -89
- data/lib/bwrap/args/construct.rb +3 -2
- data/lib/bwrap/args/environment.rb +59 -1
- data/lib/bwrap/args/features.rb +65 -3
- data/lib/bwrap/args/library.rb +17 -10
- data/lib/bwrap/args/machine_id.rb +6 -3
- data/lib/bwrap/args/mount.rb +1 -0
- data/lib/bwrap/bwrap.rb +151 -0
- data/lib/bwrap/bwrap_module.rb +26 -0
- data/lib/bwrap/config/features.rb +116 -0
- data/lib/bwrap/config.rb +96 -92
- data/lib/bwrap/execution/exceptions.rb +24 -0
- data/lib/bwrap/execution/execute.rb +4 -1
- data/lib/bwrap/execution/execution.rb +147 -3
- data/lib/bwrap/execution/labels.rb +8 -1
- data/lib/bwrap/execution/path.rb +30 -10
- data/lib/bwrap/execution.rb +6 -160
- data/lib/bwrap/output/colors.rb +0 -2
- data/lib/bwrap/output/log.rb +17 -5
- data/lib/bwrap/output/output_impl.rb +182 -0
- data/lib/bwrap/output.rb +8 -152
- data/lib/bwrap/version.rb +1 -2
- data/lib/bwrap.rb +1 -79
- data.tar.gz.sig +0 -0
- metadata +11 -19
- metadata.gz.sig +0 -0
- data/lib/bwrap/output/output.rb +0 -8
data/lib/bwrap/args/library.rb
CHANGED
@@ -6,7 +6,7 @@ require_relative "args"
|
|
6
6
|
|
7
7
|
# Class to clean up namespace for implementation specific reasons.
|
8
8
|
#
|
9
|
-
# @api
|
9
|
+
# @api private
|
10
10
|
class Bwrap::Args::Library
|
11
11
|
include Bwrap::Execution
|
12
12
|
include Bwrap::Output
|
@@ -14,6 +14,11 @@ class Bwrap::Args::Library
|
|
14
14
|
# NOTE: This caching can be made more efficient, but need to look at it later, what to do about it.
|
15
15
|
@@needed_libraries_cache ||= []
|
16
16
|
|
17
|
+
# Empties {@@needed_libraries_cache}.
|
18
|
+
def self.clear_needed_libraries_cache
|
19
|
+
@@needed_libraries_cache.clear
|
20
|
+
end
|
21
|
+
|
17
22
|
# Otherwise similar to {#needed_libraries}, but checks used libc to handle musl executables.
|
18
23
|
#
|
19
24
|
# @param executable [String] Path to the executable to find dependencies for
|
@@ -99,17 +104,17 @@ class Bwrap::Args::Library
|
|
99
104
|
binary_path, libraries_line = line.split "::SEPARATOR::"
|
100
105
|
libraries = libraries_line.split ","
|
101
106
|
|
102
|
-
@needed_libraries
|
107
|
+
(@needed_libraries & libraries).each do |library|
|
108
|
+
verb "Binding #{library} as dependency of #{binary_path}"
|
109
|
+
end
|
110
|
+
|
111
|
+
@needed_libraries |= libraries
|
103
112
|
|
104
113
|
# Also check if requisite libraries needs some libraries.
|
105
114
|
inner = Bwrap::Args::Library.new
|
106
|
-
@needed_libraries
|
115
|
+
@needed_libraries |= inner.needed_libraries libraries
|
107
116
|
|
108
|
-
|
109
|
-
libraries.each do |library|
|
110
|
-
verb "Binding #{library} as dependency of #{binary_path}"
|
111
|
-
@@needed_libraries_cache << library
|
112
|
-
end
|
117
|
+
@@needed_libraries_cache |= libraries
|
113
118
|
end
|
114
119
|
|
115
120
|
# Used by {#musl_needed_libraries}.
|
@@ -120,11 +125,13 @@ class Bwrap::Args::Library
|
|
120
125
|
matches = library_data.match(/(.*) \(0x[0-9a-f]+\)/)
|
121
126
|
library_path = matches[1]
|
122
127
|
|
123
|
-
@needed_libraries
|
128
|
+
unless @needed_libraries.include? library_path
|
129
|
+
@needed_libraries << library_path
|
130
|
+
end
|
124
131
|
|
125
132
|
# Also check if requisite libraries needs some libraries.
|
126
133
|
inner = Bwrap::Args::Library.new
|
127
|
-
@needed_libraries
|
134
|
+
@needed_libraries |= inner.musl_needed_libraries library_path
|
128
135
|
end
|
129
136
|
end
|
130
137
|
# class Library ended
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "securerandom"
|
4
|
+
require "tempfile"
|
4
5
|
|
5
6
|
require "bwrap/output"
|
6
7
|
require_relative "args"
|
@@ -24,7 +25,7 @@ class Bwrap::Args::MachineId
|
|
24
25
|
# Returning [] means that execute() will ignore this fully.
|
25
26
|
# Nil would be converted to empty string, causing spawn() to pass it as argument, causing
|
26
27
|
# bwrap to misbehave.
|
27
|
-
return unless @config
|
28
|
+
return unless @config&.machine_id
|
28
29
|
|
29
30
|
machine_id = @config.machine_id
|
30
31
|
|
@@ -51,10 +52,10 @@ class Bwrap::Args::MachineId
|
|
51
52
|
debug "Using random machine id as /etc/machine-id"
|
52
53
|
|
53
54
|
@machine_id_file = Tempfile.new "bwrap-random_machine_id-", @config.tmpdir
|
54
|
-
@machine_id_file.write SecureRandom.uuid.
|
55
|
+
@machine_id_file.write SecureRandom.uuid.tr("-", "")
|
55
56
|
@machine_id_file.flush
|
56
57
|
|
57
|
-
%W{ --ro-bind-data #{machine_id_file.fileno} /etc/machine-id }
|
58
|
+
%W{ --ro-bind-data #{@machine_id_file.fileno} /etc/machine-id }
|
58
59
|
end
|
59
60
|
|
60
61
|
# Uses `10000000000000000000000000000000` as machine id.
|
@@ -79,6 +80,8 @@ class Bwrap::Args::MachineId
|
|
79
80
|
end
|
80
81
|
|
81
82
|
# Uses file inside sandbox directory as machine id.
|
83
|
+
#
|
84
|
+
# TODO: I kind of want to deprecate this one. It may make sense, but eh... Let’s see.
|
82
85
|
private def machine_id_inside_sandbox_dir sandbox_directory
|
83
86
|
machine_id_file = "#{sandbox_directory}/machine-id"
|
84
87
|
|
data/lib/bwrap/args/mount.rb
CHANGED
data/lib/bwrap/bwrap.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#require "deep-cover" if ENV["DEEP_COVER"]
|
4
|
+
|
5
|
+
require_relative "bwrap_module"
|
6
|
+
require "bwrap/version"
|
7
|
+
require "bwrap/args/construct"
|
8
|
+
require "bwrap/config"
|
9
|
+
require "bwrap/execution"
|
10
|
+
|
11
|
+
# Executes given command under {https://github.com/containers/bubblewrap bwrap}
|
12
|
+
# using given configuration.
|
13
|
+
#
|
14
|
+
# @see ::Bwrap Bwrap module for usage example
|
15
|
+
class Bwrap::Bwrap
|
16
|
+
include Bwrap::Execution
|
17
|
+
|
18
|
+
# @param config [Bwrap::Config] Configuration used to tailor bwrap
|
19
|
+
def initialize config
|
20
|
+
# TODO: Ensure that costruct.rb and utilities it uses does not enforce Config to be valid object.
|
21
|
+
# Create a test for that also. Well, as long as that makes sense. If it doesn’t work, validate
|
22
|
+
# Config object to be valid here.
|
23
|
+
@config = config
|
24
|
+
end
|
25
|
+
|
26
|
+
# Parses command line arguments given to caller script.
|
27
|
+
#
|
28
|
+
# @note This method automatically sets output levels according parsed
|
29
|
+
# options. It is also possible to set the levels manually using
|
30
|
+
# {Bwrap::Output.handle_output_options}, for example with flags
|
31
|
+
# parsed with optparse’s `OptionParser`, found in Ruby’s standard
|
32
|
+
# library.
|
33
|
+
#
|
34
|
+
# @warning Requires optimist gem to be installed, which is not a dependency of this gem.
|
35
|
+
def parse_command_line_arguments
|
36
|
+
options = parse_options
|
37
|
+
|
38
|
+
Bwrap::Output.handle_output_options options
|
39
|
+
end
|
40
|
+
|
41
|
+
# Binds and executes given command available on running system inside bwrap.
|
42
|
+
#
|
43
|
+
# If {Config#root} has been set, given executable is scanned for necessary
|
44
|
+
# libraries and they are bound inside sandbox. This often reduces amount of
|
45
|
+
# global binds, but some miscellaneous things may need custom handling.
|
46
|
+
#
|
47
|
+
# @see Config#features about binding bigger feature sets to sandbox.
|
48
|
+
#
|
49
|
+
# Executed command is constructed using configuration passed to constructor.
|
50
|
+
# After execution has completed, bwrap will also shut down.
|
51
|
+
#
|
52
|
+
# @param command [String, Array] Command to be executed inside bwrap along with necessary arguments
|
53
|
+
# @see #run_inside_root to execute a command that already is inside sandbox.
|
54
|
+
def run command
|
55
|
+
construct = Bwrap::Args::Construct.new
|
56
|
+
construct.command = command
|
57
|
+
construct.config = @config
|
58
|
+
bwrap_args = construct.construct_bwrap_args
|
59
|
+
|
60
|
+
exec_command = [ "bwrap" ]
|
61
|
+
exec_command += bwrap_args
|
62
|
+
exec_command.append command
|
63
|
+
exec_command += @cli_args if @cli_args
|
64
|
+
|
65
|
+
execute exec_command
|
66
|
+
|
67
|
+
construct.cleanup
|
68
|
+
end
|
69
|
+
|
70
|
+
# Convenience method to executes a command that is inside bwrap.
|
71
|
+
#
|
72
|
+
# Given command is expected to already be inside {Config#root}.
|
73
|
+
#
|
74
|
+
# Calling this method is equivalent to setting {Config#command_inside_root} to `true`.
|
75
|
+
#
|
76
|
+
# @note This may have a bit unintuitive usage, as most things are checked anyway, so this is not
|
77
|
+
# akin to running something inside a chroot, but rather for convenience.
|
78
|
+
#
|
79
|
+
# @param command [String, Array] Command to be executed inside bwrap along with necessary arguments
|
80
|
+
# @see #run to execute a command that needs to be bound to the sandbox.
|
81
|
+
def run_inside_root command
|
82
|
+
if @config
|
83
|
+
config = @config.dup
|
84
|
+
config.command_inside_root = true
|
85
|
+
else
|
86
|
+
config = nil
|
87
|
+
end
|
88
|
+
|
89
|
+
construct = Bwrap::Args::Construct.new
|
90
|
+
construct.command = command
|
91
|
+
construct.config = config
|
92
|
+
bwrap_args = construct.construct_bwrap_args
|
93
|
+
|
94
|
+
exec_command = [ "bwrap" ]
|
95
|
+
exec_command += bwrap_args
|
96
|
+
exec_command.append command
|
97
|
+
exec_command += @cli_args if @cli_args
|
98
|
+
|
99
|
+
execute exec_command
|
100
|
+
|
101
|
+
construct.cleanup
|
102
|
+
end
|
103
|
+
|
104
|
+
# Parses global bwrap flags using Optimist.
|
105
|
+
#
|
106
|
+
# Sets instance variable `@cli_args`.
|
107
|
+
#
|
108
|
+
# @warning Requires optimist gem to be installed, which is not a dependency of this gem.
|
109
|
+
#
|
110
|
+
# @api private
|
111
|
+
# @return [Hash] options parsed by `Optimist.options`
|
112
|
+
private def parse_options
|
113
|
+
begin
|
114
|
+
require "optimist"
|
115
|
+
rescue LoadError => e
|
116
|
+
puts "Failed to load optimist gem. In order to use Bwrap::Bwrap#parse_command_line_arguments, " \
|
117
|
+
"ensure optimist gem is present for example in your Gemfile."
|
118
|
+
puts
|
119
|
+
raise e
|
120
|
+
end
|
121
|
+
|
122
|
+
options = Optimist.options do
|
123
|
+
version ::Bwrap::VERSION
|
124
|
+
|
125
|
+
banner "Usage:"
|
126
|
+
banner " #{$PROGRAM_NAME} [global options]\n \n"
|
127
|
+
banner "Global options:"
|
128
|
+
opt :verbose,
|
129
|
+
"Show verbose output",
|
130
|
+
short: "v"
|
131
|
+
opt :debug,
|
132
|
+
"Show debug output (useful when debugging a problem)",
|
133
|
+
short: "d"
|
134
|
+
opt :trace,
|
135
|
+
"Show trace output (noisiest, probably not useful for most of time)",
|
136
|
+
short: :none
|
137
|
+
opt :version,
|
138
|
+
"Print version and exit",
|
139
|
+
short: "V"
|
140
|
+
opt :help,
|
141
|
+
"Show help message",
|
142
|
+
short: "h"
|
143
|
+
|
144
|
+
educate_on_error
|
145
|
+
end
|
146
|
+
|
147
|
+
@cli_args = ARGV.dup
|
148
|
+
|
149
|
+
options
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# ruby-bwrap provides easy-to-use interface to run complex programs in sandboxes created with
|
4
|
+
# {https://github.com/containers/bubblewrap bubblewrap}.
|
5
|
+
#
|
6
|
+
# To run a program inside bubblewrap, a wrapper executable can be created. For example:
|
7
|
+
#
|
8
|
+
# require "bwrap"
|
9
|
+
#
|
10
|
+
# config = Bwrap::Config.new
|
11
|
+
# config.user = "dummy_user"
|
12
|
+
# config.full_system_mounts = true
|
13
|
+
# config.binaries_from = %w{
|
14
|
+
# /bin
|
15
|
+
# /usr/bin
|
16
|
+
# }
|
17
|
+
#
|
18
|
+
# bwrap = Bwrap::Bwrap.new config
|
19
|
+
# bwrap.parse_command_line_arguments
|
20
|
+
# bwrap.run "/bin/true"
|
21
|
+
#
|
22
|
+
# There also are few generic utilities, {Bwrap::Output} for handling output of scripts and
|
23
|
+
# {Bwrap::Execution} to run executables.
|
24
|
+
module Bwrap
|
25
|
+
# Empty module.
|
26
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Bwrap::Config
|
4
|
+
# Methods to enable or disable feature sets to control various aspects of sandboxing.
|
5
|
+
class Features
|
6
|
+
# @abstract
|
7
|
+
#
|
8
|
+
# Base of all features.
|
9
|
+
class Base
|
10
|
+
# @param features [Bwrap::Config::Features] Instance of features object in {Config}
|
11
|
+
def initialize features
|
12
|
+
@features = features
|
13
|
+
end
|
14
|
+
|
15
|
+
# Checks if the feature has been enabled.
|
16
|
+
#
|
17
|
+
# @return [Boolean] whether feature is enabled
|
18
|
+
def enabled?
|
19
|
+
@enabled
|
20
|
+
end
|
21
|
+
|
22
|
+
# Enable the feature.
|
23
|
+
def enable
|
24
|
+
@enabled = true
|
25
|
+
end
|
26
|
+
|
27
|
+
# Disable the feature.
|
28
|
+
def disable
|
29
|
+
@enabled = false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Defines Bash feature set.
|
34
|
+
class Bash < Base
|
35
|
+
# Nya.
|
36
|
+
end
|
37
|
+
|
38
|
+
# Defines Nscd feature set.
|
39
|
+
#
|
40
|
+
# nscd is short of name service cache daemon. It may make sense to
|
41
|
+
# have this class under another name, but I don’t know how nscd specific
|
42
|
+
# this feature can be, so this name it is for now.
|
43
|
+
class Nscd < Base
|
44
|
+
# Nya.
|
45
|
+
end
|
46
|
+
|
47
|
+
# Defines Ruby feature set.
|
48
|
+
#
|
49
|
+
# Implies {Nscd} feature.
|
50
|
+
class Ruby < Base
|
51
|
+
# Extra libraries to be loaded from `RbConfig::CONFIG["rubyarchdir"]`.
|
52
|
+
#
|
53
|
+
# @note This is only required to be called if extra dependencies are necessary.
|
54
|
+
# For example, psych.so requires libyaml.so.
|
55
|
+
#
|
56
|
+
# @return [Array] list of needed libraries.
|
57
|
+
#
|
58
|
+
# @overload stdlib
|
59
|
+
# @overload stdlib=(libs)
|
60
|
+
attr_reader :stdlib
|
61
|
+
|
62
|
+
def initialize features
|
63
|
+
super features
|
64
|
+
|
65
|
+
@gem_env_paths = true
|
66
|
+
@stdlib = []
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return true if bindirs from “gem environment” should be added to sandbox.
|
70
|
+
def gem_env_paths?
|
71
|
+
@gem_env_paths
|
72
|
+
end
|
73
|
+
|
74
|
+
# Enable Ruby feature set.
|
75
|
+
#
|
76
|
+
# Among others, binds `RbConfig::CONFIG["sitedir"]` so scripts works.
|
77
|
+
#
|
78
|
+
# @note This does not allow development headers needed for compilation for now.
|
79
|
+
# I’ll look at it after I have an use for it.
|
80
|
+
#
|
81
|
+
# @note Also enables {Nscd} feature.
|
82
|
+
def enable
|
83
|
+
super
|
84
|
+
|
85
|
+
@features.nscd.enable
|
86
|
+
end
|
87
|
+
|
88
|
+
# @see #stdlib
|
89
|
+
def stdlib= libs
|
90
|
+
# Just a little check to have error earlier.
|
91
|
+
libs.each do |lib|
|
92
|
+
unless File.exist? "#{RbConfig::CONFIG["rubyarchdir"]}/#{lib}.so"
|
93
|
+
raise "Library “#{lib}” passed to Bwrap::Config::Ruby.stdlib= does not exist."
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
@stdlib = libs
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# @return [Bash] Instance of feature class for Bash
|
102
|
+
def bash
|
103
|
+
@bash ||= Bash.new self
|
104
|
+
end
|
105
|
+
|
106
|
+
# @return [Nscd] Instance of feature class for nscd
|
107
|
+
def nscd
|
108
|
+
@nscd ||= Nscd.new self
|
109
|
+
end
|
110
|
+
|
111
|
+
# @return [Ruby] Instance of feature class for Ruby
|
112
|
+
def ruby
|
113
|
+
@ruby ||= Ruby.new self
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
data/lib/bwrap/config.rb
CHANGED
@@ -3,13 +3,60 @@
|
|
3
3
|
require "bwrap/output"
|
4
4
|
require "bwrap/version"
|
5
5
|
|
6
|
-
#
|
6
|
+
# Features classes, used through {Config#features}.
|
7
|
+
require_relative "config/features"
|
8
|
+
|
9
|
+
# Represents configuration used to tailor bwrap execution.
|
10
|
+
#
|
11
|
+
# @developer_note
|
12
|
+
# Logger methods (debug, warn and so on) can’t be used here as logger
|
13
|
+
# isn’t initialized before this class.
|
14
|
+
#
|
15
|
+
# For same reason, it’s not advised to execute anything here.
|
7
16
|
#
|
8
|
-
#
|
9
|
-
#
|
17
|
+
# Note that all attributes also have writers, even though they are not documented.
|
18
|
+
#
|
19
|
+
# @todo Add some documentation about syntax where necessary, like for #binaries_from.
|
10
20
|
class Bwrap::Config
|
21
|
+
# Array of audio schemes usable inside chroot.
|
22
|
+
#
|
23
|
+
# Currently supports:
|
24
|
+
# - :pulseaudio
|
25
|
+
#
|
26
|
+
attr_accessor :audio
|
27
|
+
|
28
|
+
# Set to `true` if command given to {Bwrap::Bwrap#run} is expected to
|
29
|
+
# be inside sandbox, and not bound from host.
|
30
|
+
#
|
31
|
+
# @return [Boolean] `true` if executed command is inside sandbox
|
32
|
+
attr_accessor :command_inside_root
|
33
|
+
|
34
|
+
attr_accessor :extra_executables
|
35
|
+
|
36
|
+
# TODO: IIRC this doesn’t match the reality any more. So write correct documentation.
|
37
|
+
#
|
38
|
+
# Causes libraries required by the executable given to {Bwrap#run} to be
|
39
|
+
# mounted inside sandbox.
|
40
|
+
#
|
41
|
+
# Often it is enough to use this flag instead of binding all system libraries
|
42
|
+
# using {#libdir_mounts=}
|
43
|
+
#
|
44
|
+
# @return [Boolean] true if Linux library loaders are mounted inside chroot
|
45
|
+
attr_accessor :full_system_mounts
|
46
|
+
|
11
47
|
attr_accessor :hostname
|
12
48
|
|
49
|
+
# Set to true if basic system directories, like /usr/lib and /usr/lib64,
|
50
|
+
# should be bound inside chroot.
|
51
|
+
#
|
52
|
+
# /usr/bin can be mounted using {Config#binaries_from=}.
|
53
|
+
#
|
54
|
+
# Often it is enough to use {#full_system_mounts=} instead of binding all
|
55
|
+
# system libraries using this flag.
|
56
|
+
#
|
57
|
+
# @return [Boolean] true if libdirs are mounted to the chroot
|
58
|
+
attr_accessor :libdir_mounts
|
59
|
+
|
13
60
|
# What should be used as /etc/machine_id file.
|
14
61
|
#
|
15
62
|
# If not specified, no /etc/machine_id handling is done.
|
@@ -24,6 +71,9 @@ class Bwrap::Config
|
|
24
71
|
# Given file as bound as /etc/machine_id.
|
25
72
|
attr_accessor :machine_id
|
26
73
|
|
74
|
+
# @return [Boolean] true if network should be shared from host.
|
75
|
+
attr_accessor :share_net
|
76
|
+
|
27
77
|
# Name of the user inside chroot.
|
28
78
|
#
|
29
79
|
# This is optional and defaults to no user.
|
@@ -35,34 +85,23 @@ class Bwrap::Config
|
|
35
85
|
# @return [Boolean] Whether Xorg specific binds are used.
|
36
86
|
attr_accessor :xorg_application
|
37
87
|
|
38
|
-
# Array of
|
88
|
+
# Array of directories to be bind mounted in sandbox.
|
39
89
|
#
|
40
|
-
#
|
41
|
-
# - :pulseaudio
|
90
|
+
# Given paths are also added to PATH environment variable inside sandbox.
|
42
91
|
#
|
43
|
-
|
44
|
-
|
45
|
-
#
|
46
|
-
attr_accessor :share_net
|
47
|
-
|
48
|
-
# TODO: This should cause Bind#full_system_mounts to mount /lib64/ld-linux-x86-64.so.2 and so on,
|
49
|
-
# probably according executable type of specified command. But that needs some magic.
|
92
|
+
# @hint At least on SUSE, many executables are symlinks to /etc/alternatives/*,
|
93
|
+
# which in turn symlinks to versioned executable under the same bindir.
|
94
|
+
# To use these executables, /etc/alternatives should also be bound:
|
50
95
|
#
|
51
|
-
#
|
96
|
+
# config.ro_binds["/etc/alternatives"] = "/etc/alternatives"
|
52
97
|
#
|
53
|
-
# @return [
|
54
|
-
|
98
|
+
# @return [Array] Paths to directories where binaries are looked from.
|
99
|
+
attr_reader :binaries_from
|
55
100
|
|
56
|
-
#
|
57
|
-
# should be bound inside chroot.
|
101
|
+
# Paths to be added to sandbox instance’s PATH environment variable.
|
58
102
|
#
|
59
|
-
#
|
60
|
-
|
61
|
-
# @return [Boolean] true if libdirs are mounted to the chroot
|
62
|
-
attr_accessor :libdir_mounts
|
63
|
-
|
64
|
-
# Array of directories to be bind mounted and used to construct PATH environment variable.
|
65
|
-
attr_reader :binaries_from
|
103
|
+
# @see #add_env_path
|
104
|
+
attr_reader :env_paths
|
66
105
|
|
67
106
|
# TODO: Document this.
|
68
107
|
# TODO: I wonder if this should just be removed. I don’t know, this is a bit ...
|
@@ -72,71 +111,34 @@ class Bwrap::Config
|
|
72
111
|
# Use given directory as root. End result is similar to classic chroot.
|
73
112
|
attr_reader :root
|
74
113
|
|
75
|
-
#
|
114
|
+
# @overload ro_binds
|
115
|
+
# `Hash`[`Pathname`] => `Pathname` containing custom read-only binds.
|
116
|
+
# @overload ro_binds=
|
117
|
+
# Set given hash of paths to be bound with --ro-bind.
|
118
|
+
#
|
119
|
+
# Key is source path, value is destination path.
|
120
|
+
#
|
121
|
+
# Given source paths must exist.
|
76
122
|
attr_reader :ro_binds
|
77
123
|
|
78
|
-
#
|
124
|
+
# @overload tmpdir
|
125
|
+
# Path to temporary directory.
|
79
126
|
#
|
80
|
-
#
|
127
|
+
# Defaults to Dir.tmpdir.
|
128
|
+
# @overload tmpdir=(dir)
|
129
|
+
# Sets given directory as temporary directory for certain operations.
|
130
|
+
#
|
131
|
+
# @note Requires `dir` to be path to existing directory.
|
132
|
+
# @raise [RuntimeError] If given directory does not exist
|
133
|
+
# @param dir Path to temporary directory
|
81
134
|
attr_reader :tmpdir
|
82
135
|
|
83
|
-
# Methods to enable or disable feature sets to control various aspects of sandboxing.
|
84
|
-
class Features
|
85
|
-
# Defines Ruby feature set.
|
86
|
-
class Ruby
|
87
|
-
# @return [Array] list of needed libraries.
|
88
|
-
attr_reader :stdlib
|
89
|
-
|
90
|
-
def initialize
|
91
|
-
@stdlib = []
|
92
|
-
end
|
93
|
-
|
94
|
-
# @see enabled=
|
95
|
-
def enabled?
|
96
|
-
@enabled
|
97
|
-
end
|
98
|
-
|
99
|
-
# Enable Ruby feature set.
|
100
|
-
#
|
101
|
-
# Among others, binds RbConfig::CONFIG["sitedir"] so scripts works.
|
102
|
-
#
|
103
|
-
# @note This does not allow development headers needed for compilation for now.
|
104
|
-
# I’ll look at it after I have an use for it.
|
105
|
-
def enable
|
106
|
-
@enabled = true
|
107
|
-
end
|
108
|
-
|
109
|
-
# Disable Ruby feature set.
|
110
|
-
def disable
|
111
|
-
@enabled = false
|
112
|
-
end
|
113
|
-
|
114
|
-
# Extra libraries to be loaded from `RbConfig::CONFIG["rubyarchdir"]`.
|
115
|
-
#
|
116
|
-
# @note This is only required to be called if extra dependencies are necessary.
|
117
|
-
# For example, psych.so requires libyaml.so.
|
118
|
-
def stdlib= libs
|
119
|
-
# Just a little check to have error earlier.
|
120
|
-
libs.each do |lib|
|
121
|
-
unless File.exist? "#{RbConfig::CONFIG["rubyarchdir"]}/#{lib}.so"
|
122
|
-
raise "Library “#{lib}” passed to Bwrap::Config::Ruby.stdlib= does not exist."
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
@stdlib = libs
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
# @return [Ruby] Instance of feature class for Ruby
|
131
|
-
def ruby
|
132
|
-
@ruby ||= Ruby.new
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
136
|
def initialize
|
137
|
+
@audio = []
|
137
138
|
@binaries_from = []
|
139
|
+
@env_paths = []
|
140
|
+
@ro_binds = {}
|
138
141
|
@tmpdir = Dir.tmpdir
|
139
|
-
@audio = []
|
140
142
|
end
|
141
143
|
|
142
144
|
def binaries_from= array
|
@@ -178,14 +180,13 @@ class Bwrap::Config
|
|
178
180
|
@root = directory
|
179
181
|
end
|
180
182
|
|
181
|
-
# Set given hash of paths to be bound with --ro-bind.
|
182
|
-
#
|
183
|
-
# Key is source path, value is destination path.
|
184
|
-
#
|
185
|
-
# Given source paths must exist.
|
186
183
|
def ro_binds= binds
|
187
184
|
@ro_binds = {}
|
188
185
|
binds.each do |source_path, destination_path|
|
186
|
+
if destination_path.nil?
|
187
|
+
raise "binds should be key-value storage of Strings, for example a Hash."
|
188
|
+
end
|
189
|
+
|
189
190
|
source_path = Pathname.new source_path
|
190
191
|
unless source_path.exist?
|
191
192
|
raise "Given read only bind does not exist. Please check path “#{source_path}” is correct."
|
@@ -197,14 +198,17 @@ class Bwrap::Config
|
|
197
198
|
end
|
198
199
|
end
|
199
200
|
|
200
|
-
#
|
201
|
-
#
|
202
|
-
# @note Requires `dir` to be path to existing directory.
|
203
|
-
# @raise [RuntimeError] If given directory does not exist
|
204
|
-
# @param dir Path to temporary directory
|
201
|
+
# See attr_accessor :tmpdir for documentation.
|
205
202
|
def tmpdir= dir
|
206
203
|
raise "Directory to be set as a temporary directory, “#{dir}”, does not exist." unless Dir.exist? dir
|
207
204
|
|
208
205
|
@tmpdir = dir
|
209
206
|
end
|
207
|
+
|
208
|
+
# Add a path to sandbox instance’s PATH environment variable.
|
209
|
+
#
|
210
|
+
# @param path [String] Path to be added added to PATH environment variable
|
211
|
+
def add_env_path path
|
212
|
+
@env_paths << path
|
213
|
+
end
|
210
214
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bwrap::Execution
|
4
|
+
# Unspecified execution related error.
|
5
|
+
class CommandError < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
# Signifies that command execution has failed.
|
9
|
+
class ExecutionFailed < CommandError
|
10
|
+
end
|
11
|
+
|
12
|
+
# Thrown if given command was not found.
|
13
|
+
class CommandNotFound < CommandError
|
14
|
+
# Command that was looked at.
|
15
|
+
attr_reader :command
|
16
|
+
|
17
|
+
def initialize command:
|
18
|
+
@command = command
|
19
|
+
msg = "Failed to find #{command} from PATH."
|
20
|
+
|
21
|
+
super msg
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -3,11 +3,14 @@
|
|
3
3
|
# force_encoding modifies string, so can’t freeze strings.
|
4
4
|
|
5
5
|
require "bwrap/output"
|
6
|
+
require_relative "exceptions"
|
6
7
|
require_relative "execution"
|
7
8
|
|
8
9
|
# Methods that performs actual execution logic.
|
9
10
|
#
|
10
|
-
# @
|
11
|
+
# @note This is kind of pseudo-internal API. Hopefully there won’t be breaking changes.
|
12
|
+
# But please use {Bwrap::Execution} instead of relying functionality of this class,
|
13
|
+
# outside of {.prepend_rootcmd}.
|
11
14
|
class Bwrap::Execution::Execute
|
12
15
|
include Bwrap::Output
|
13
16
|
|