bwrap 1.0.0.pre.alpha3 → 1.0.0.pre.alpha4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d7a362da994cec63d76530772a6740d68e9cf442f4bb43dfc39579ce6c10c40e
4
- data.tar.gz: 0ec62bee38e4729320ec365490e94c03f1f33f84e570e186ac009b587162ea24
3
+ metadata.gz: 5101d7848dccd6da3f68fc02f08b37ec1cfadc516b45cb964265a3f0a60e8ea3
4
+ data.tar.gz: 6dbf98ccc5faba3385ce8fe6f9890f9e7369860531e4161c8092611c18a8ca02
5
5
  SHA512:
6
- metadata.gz: 65e1ad6f76b55f0b9fbabc2066eb10000ab286d6440070331dd8244f608f0de39e3ccf1f54b6e663727da32c5c587a4ae87717d5f8276444f835caaf3ff0618a
7
- data.tar.gz: 5298f24103bb9c4290906fed7e6a5925a85228482f17cb2516bb6a3a50ace7c3fcb2d17de00abd1bd994d7cdd97fe420451631f50fe8792c247bab577a20ea4e
6
+ metadata.gz: 690e7e3f4911d80d5384aa10fc8c7dab6ed86c597dc691a66a396efccf15dc06e3ee29586afe687e4f92670eea049d2e76e034a2147eed9a9abcb9b894c99e67
7
+ data.tar.gz: d0a5312ab4ef5814885fd928f1359fd9ba69d7f36224c8671d79396ab635f1f8c23fd21a16712e62ca4b566cc51138b0f654e5cd8e3304f30cf10d492bbdc991
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changes
2
2
 
3
+ ## 1.0.0-alpha4 (22.11.2021)
4
+
5
+ * Allow use without home directory set
6
+ * Bwrap#parse_command_line_arguments is no longer run when Bwrap is initialized
7
+ * Made pulseaudio optional
8
+ * Changed --share-net to be added only if requested
9
+ * Added Config#root= to specify path used as writable root
10
+ * Added Config#full_system_mounts to control whether library loaders are mounted inside chroot
11
+ * Added Config#libdir_mounts
12
+ * Added Config#features
13
+
3
14
  ## 1.0.0-alpha3 (14.11.2021)
4
15
 
5
16
  * Avoid frozen string literal modification
@@ -1,32 +1,90 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "bwrap/execution"
4
+ require "bwrap/output"
3
5
  require_relative "args"
6
+ require_relative "library"
4
7
 
5
8
  # Bind arguments for bwrap.
6
- module Bwrap::Args::Bind
9
+ class Bwrap::Args::Bind
10
+ include Bwrap::Execution
11
+ include Bwrap::Output
12
+
13
+ # Array of parameters passed to bwrap.
14
+ attr_writer :args
15
+
16
+ # @see Bwrap::Args::Construct#command=
17
+ #
18
+ # @see (see Bwrap::Args::Construct#command=)
19
+ attr_writer :command
20
+
21
+ # Instance of {Config}.
22
+ attr_writer :config
23
+
24
+ # Instance of {Bwrap::Args::Environment}.
25
+ attr_writer :environment
26
+
27
+ # Inner class to clean up namespace for implementation specific reasons.
28
+ #
29
+ # @api internal
30
+ class Mime
31
+ include Bwrap::Execution
32
+ include Bwrap::Output
33
+
34
+ # Name given to {#initialize}.
35
+ attr_reader :executable_name
36
+
37
+ # Either path given to {#initialize} or one parsed from shebang.
38
+ attr_reader :executable_path
39
+
40
+ def initialize executable_name, executable_path
41
+ @executable_name = executable_name
42
+ @executable_path = executable_path
43
+ end
44
+
45
+ # Used by {Bwrap::Args::Bind#libs_command_requires}.
46
+ #
47
+ # @return false if caller should also return
48
+ def resolve_mime_type
49
+ mime_type = execvalue %W{ file --brief --mime-type #{@executable_path} }
50
+ return true unless mime_type[0..6] == "text/x-"
51
+
52
+ shebang = File.open @executable_path, &:readline
53
+ if shebang[0..1] != "#!"
54
+ warn "Executable #{@executable_name} was recognized as #{mime_type} but does not have " \
55
+ "proper shebang line. Skipping automatic library mounts."
56
+ return false
57
+ end
58
+
59
+ shebang = shebang.delete_prefix("#!").strip
60
+ real_executable, _args = shebang.split " ", 2
61
+ @executable_path = real_executable
62
+
63
+ true
64
+ end
65
+ end
66
+
7
67
  # Arguments to bind /dev/dri from host to sandbox.
8
- private def bind_dev_dri
9
- %w{ --dev-bind /dev/dri /dev/dri }
68
+ def bind_dev_dri
69
+ @args.append %w{ --dev-bind /dev/dri /dev/dri }
10
70
  end
11
71
 
12
72
  # Arguments to bind /sys/dev/char from host to sandbox.
13
- private def bind_sys_dev_char
14
- %w{ --ro-bind /sys/dev/char /sys/dev/char }
73
+ def bind_sys_dev_char
74
+ @args.append %w{ --ro-bind /sys/dev/char /sys/dev/char }
15
75
  end
16
76
 
17
77
  # Arguments to bind /sys/devices/pci0000:00 from host to sandbox.
18
- private def bind_pci_devices
19
- %w{ --ro-bind /sys/devices/pci0000:00 /sys/devices/pci0000:00 }
78
+ def bind_pci_devices
79
+ @args.append %w{ --ro-bind /sys/devices/pci0000:00 /sys/devices/pci0000:00 }
20
80
  end
21
81
 
22
82
  # Arguments to bind home directory from sandbox directory (`#{@config.sandbox_directory}/home`)
23
83
  # as `/home/#{@config.user}`.
24
84
  #
25
85
  # @note Requires @config.user to be set.
26
- private def bind_home_directory
27
- unless @config.user
28
- raise "Tried to bind user directory without user being set."
29
- end
86
+ def bind_home_directory
87
+ return unless @config.user
30
88
 
31
89
  home_directory = "#{@config.sandbox_directory}/home"
32
90
 
@@ -36,11 +94,12 @@ module Bwrap::Args::Bind
36
94
 
37
95
  @environment["HOME"] = "/home/#{@config.user}"
38
96
 
39
- %W{ --bind #{home_directory} /home/#{@config.user} }
97
+ debug "Using #{home_directory} as /home/#{@config.user}"
98
+ @args.append %W{ --bind #{home_directory} /home/#{@config.user} }
40
99
  end
41
100
 
42
101
  # Arguments to read-only bind whole system inside sandbox.
43
- private def full_system_mounts
102
+ def full_system_mounts
44
103
  bindir_mounts = []
45
104
  binaries_from = @config.binaries_from
46
105
  binaries_from.each do |path|
@@ -48,6 +107,38 @@ module Bwrap::Args::Bind
48
107
  end
49
108
  @environment["PATH"] = binaries_from.join(":")
50
109
 
110
+ @args.append bindir_mounts
111
+
112
+ if debug?
113
+ debug "Using following bindir mounts:\n" \
114
+ "#{bindir_mounts}\n" \
115
+ "(Odd is key, even is value)"
116
+ end
117
+
118
+ libdir_mounts
119
+
120
+ return unless @config.full_system_mounts
121
+
122
+ loader_binds
123
+ libs_command_requires
124
+ end
125
+
126
+ # These are something user can specify to do custom --ro-bind binds.
127
+ def custom_read_only_binds
128
+ return unless @config.ro_binds
129
+
130
+ binds = []
131
+ @config.ro_binds.each do |source_path, destination_path|
132
+ binds << "--ro-bind" << source_path.to_s << destination_path.to_s
133
+ end
134
+
135
+ @args.append binds
136
+ end
137
+
138
+ # Used by {#full_system_mounts}.
139
+ private def libdir_mounts
140
+ return unless @config.libdir_mounts
141
+
51
142
  libdir_mounts = %w{
52
143
  --ro-bind /lib /lib
53
144
  --ro-bind /lib64 /lib64
@@ -55,24 +146,54 @@ module Bwrap::Args::Bind
55
146
  --ro-bind /usr/lib64 /usr/lib64
56
147
  }
57
148
 
58
- system_mounts = bindir_mounts + libdir_mounts
59
149
  if debug?
60
- debug "Using following system mounts:\n" \
61
- "#{system_mounts}\n" \
150
+ debug "Using following libdir mounts:\n" \
151
+ "#{libdir_mounts}\n" \
62
152
  "(Odd is key, even is value)"
63
153
  end
64
- system_mounts
154
+
155
+ @args.append libdir_mounts
65
156
  end
66
157
 
67
- # These are something user can specify to do custom --ro-bind binds.
68
- private def custom_read_only_binds
69
- return [] unless @config.ro_binds
158
+ # Used by {#full_system_mounts}.
159
+ private def loader_binds
160
+ loader_mounts = []
161
+ path = "/lib64/ld-linux-x86-64.so.2"
162
+ loader_mounts << "--ro-bind" << path << path if File.exist? path
163
+ path = "/lib/ld-linux.so.2"
164
+ loader_mounts << "--ro-bind" << path << path if File.exist? path
70
165
 
71
- binds = []
72
- @config.ro_binds.each do |source_path, destination_path|
73
- binds << "--ro-bind" << source_path.to_s << destination_path.to_s
166
+ @args.append loader_mounts
167
+ end
168
+
169
+ # Does some inspection to find out libraries given executable needs in order to work.
170
+ #
171
+ # Used by {#full_system_mounts}.
172
+ #
173
+ # @warning scanelf does not play with spaces in names well. This method assumes that libraries
174
+ # have no spaces in names, though binaries can have.
175
+ #
176
+ # @todo Ensure scanelf is available (and throw proper error if it is not, telling to not use full_system_mounts option.)
177
+ private def libs_command_requires
178
+ executable_name = @command.is_a?(String) && @command || @command[0]
179
+ executable_path = which executable_name
180
+
181
+ # TODO: Put this behind additional flag for extra control/sanity.
182
+ # Some executables are shell scripts and similar. For them we need to use the interpreter.
183
+
184
+ mime = Mime.new executable_name, executable_path
185
+ return unless mime.resolve_mime_type
186
+
187
+ # Then find out required libraries
188
+
189
+ library_mounts = []
190
+
191
+ library_object = Bwrap::Args::Library.new
192
+ library_object.needed_libraries(mime.executable_path).each do |library|
193
+ library_mounts << "--ro-bind" << library << library
74
194
  end
75
195
 
76
- binds
196
+ @args.append library_mounts
77
197
  end
78
- end
198
+
199
+ end
@@ -5,46 +5,56 @@ require "tempfile"
5
5
  require "bwrap/output"
6
6
  require_relative "bind"
7
7
  require_relative "environment"
8
+ require_relative "features"
8
9
  require_relative "machine_id"
9
10
  require_relative "mount"
10
11
 
11
12
  # Constructs arguments for bwrap execution.
12
13
  class Bwrap::Args::Construct
13
14
  include Bwrap::Output
14
- include Bwrap::Args::Bind
15
15
  include Bwrap::Args::Mount
16
16
 
17
17
  attr_writer :config
18
18
 
19
+ # Command that is executed inside bwrap sandbox.
20
+ #
21
+ # @note This is not used for anything vital, but some things, like
22
+ # setting {Config#full_system_mounts=} uses this to resolve some
23
+ # additional data.
24
+ #
25
+ # @param command [Array, String] Command with arguments
26
+ attr_writer :command
27
+
19
28
  # Constructs arguments for bwrap execution.
20
29
  def construct_bwrap_args
21
- @environment = Bwrap::Args::Environment.new
22
- @environment.config = @config
23
- @machine_id = Bwrap::Args::MachineId.new
24
- @machine_id.config = @config
25
-
26
- [
27
- xauthority_args,
28
- @machine_id.machine_id,
29
- resolv_conf,
30
- full_system_mounts,
31
- custom_read_only_binds,
32
- create_user_dir,
33
- read_only_pulseaudio,
34
- dev_mount,
35
- bind_dev_dri,
36
- bind_sys_dev_char,
37
- bind_pci_devices,
38
- proc_mount,
39
- tmp_as_tmpfs,
40
- bind_home_directory,
41
- "--unshare-all",
42
- share_net,
43
- hostname,
44
- @environment.environment_variables,
45
- "--die-with-parent",
46
- "--new-session"
47
- ]
30
+ @args = []
31
+ create_objects
32
+
33
+ root_mount
34
+ xauthority_args
35
+ machine_id = @machine_id.machine_id
36
+ @args.append machine_id if machine_id
37
+ resolv_conf
38
+ @bind.full_system_mounts
39
+ @features.feature_binds
40
+ @bind.custom_read_only_binds
41
+ create_user_dir
42
+ read_only_pulseaudio
43
+ dev_mount
44
+ @bind.bind_dev_dri
45
+ @bind.bind_sys_dev_char
46
+ @bind.bind_pci_devices
47
+ proc_mount
48
+ tmp_as_tmpfs
49
+ @bind.bind_home_directory
50
+ @args.append "--unshare-all"
51
+ share_net
52
+ hostname
53
+ @args.append @environment.environment_variables
54
+ @args.append "--die-with-parent"
55
+ @args.append "--new-session"
56
+
57
+ @args.compact
48
58
  end
49
59
 
50
60
  # Performs cleanup operations after execution.
@@ -52,13 +62,32 @@ class Bwrap::Args::Construct
52
62
  @machine_id&.cleanup
53
63
  end
54
64
 
65
+ # Used by {#construct_bwrap_args}.
66
+ private def create_objects
67
+ @bind = Bwrap::Args::Bind.new
68
+ @bind.args = @args
69
+ @bind.command = @command
70
+ @bind.config = @config
71
+
72
+ @environment = Bwrap::Args::Environment.new
73
+ @environment.config = @config
74
+ @bind.environment = @environment
75
+
76
+ @features = Bwrap::Args::Features.new
77
+ @features.args = @args
78
+ @features.config = @config
79
+
80
+ @machine_id = Bwrap::Args::MachineId.new
81
+ @machine_id.config = @config
82
+ end
83
+
55
84
  # Arguments for generating .Xauthority file.
56
85
  private def xauthority_args
57
- return [] unless @config.xorg_application
86
+ return unless @config.xorg_application
58
87
 
59
88
  xauth_args = %W{ --ro-bind #{Dir.home}/.Xauthority #{Dir.home}/.Xauthority }
60
89
  debug "Binding following .Xauthority file: #{Dir.home}/.Xauthority"
61
- xauth_args
90
+ @args.append xauth_args
62
91
  end
63
92
 
64
93
  # Arguments to read-only bind /etc/resolv.conf.
@@ -68,25 +97,29 @@ class Bwrap::Args::Construct
68
97
  source_resolv_conf = source_resolv_conf.realpath
69
98
 
70
99
  debug "Binding #{source_resolv_conf} as /etc/resolv.conf"
71
- %W{ --ro-bind #{source_resolv_conf} /etc/resolv.conf }
100
+ @args.append %W{ --ro-bind #{source_resolv_conf} /etc/resolv.conf }
72
101
  end
73
102
 
74
103
  # Arguments to create `/run/user/#{uid}`.
75
104
  private def create_user_dir
76
105
  trace "Creating directory /run/user/#{uid}"
77
- %W{ --dir /run/user/#{uid} }
106
+ @args.append %W{ --dir /run/user/#{uid} }
78
107
  end
79
108
 
80
109
  # Arguments to bind necessary pulseaudio data for audio support.
81
110
  private def read_only_pulseaudio
111
+ return unless @config.audio.include? :pulseaudio
112
+
82
113
  debug "Binding pulseaudio"
83
- %W{ --ro-bind /run/user/#{uid}/pulse /run/user/#{uid}/pulse }
114
+ @args.append %W{ --ro-bind /run/user/#{uid}/pulse /run/user/#{uid}/pulse }
84
115
  end
85
116
 
86
117
  # Arguments to allow network connection inside sandbox.
87
118
  private def share_net
119
+ return unless @config.share_net
120
+
88
121
  verb "Sharing network"
89
- %w{ --share-net }
122
+ @args.append %w{ --share-net }
90
123
  end
91
124
 
92
125
  # Arguments to set hostname to whatever is configured.
@@ -94,7 +127,7 @@ class Bwrap::Args::Construct
94
127
  return unless @config.hostname
95
128
 
96
129
  debug "Setting hostname to #{@config.hostname}"
97
- %W{ --hostname #{@config.hostname} }
130
+ @args.append %W{ --hostname #{@config.hostname} }
98
131
  end
99
132
 
100
133
  # Returns current user id.
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bwrap/output"
4
+ require_relative "args"
5
+ require_relative "library"
6
+
7
+ # Feature parameter construction.
8
+ #
9
+ # @see Config::Features
10
+ class Bwrap::Args::Features < Hash
11
+ include Bwrap::Output
12
+
13
+ # {Array} of parameters passed to bwrap.
14
+ attr_writer :args
15
+
16
+ # Instance of {Config}.
17
+ attr_writer :config
18
+
19
+ def feature_binds
20
+ ruby_binds
21
+ end
22
+
23
+ # @note This does not allow development headers needed for compilation for now. I’ll look at it after I have an use for it.
24
+ private def ruby_binds
25
+ return unless @config.features.ruby.enabled?
26
+
27
+ # Bind system paths so scripts works inside sandbox.
28
+
29
+ mounts = []
30
+ mounts << "--ro-bind" << RbConfig::CONFIG["sitedir"] << RbConfig::CONFIG["sitedir"]
31
+ mounts << "--ro-bind" << RbConfig::CONFIG["rubyhdrdir"] << RbConfig::CONFIG["rubyhdrdir"]
32
+ mounts << "--ro-bind" << RbConfig::CONFIG["rubylibdir"] << RbConfig::CONFIG["rubylibdir"]
33
+ mounts << "--ro-bind" << RbConfig::CONFIG["vendordir"] << RbConfig::CONFIG["vendordir"]
34
+
35
+ @args.append mounts
36
+
37
+ # Create binds for required system libraries.
38
+ #
39
+ # These are in path like /usr/lib64/ruby/2.5.0/x86_64-linux-gnu/,
40
+ # and as they are mostly shared libraries, they may have some extra
41
+ # dependencies that also need to be bound inside the sandbox.
42
+
43
+ library_mounts = []
44
+ library = Bwrap::Args::Library.new
45
+ @config.features.ruby.stdlib.each do |lib|
46
+ path = "#{RbConfig::CONFIG["rubyarchdir"]}/#{lib}.so"
47
+
48
+ library.needed_libraries(path).each do |library|
49
+ library_mounts << "--ro-bind" << library << library
50
+ end
51
+ end
52
+
53
+ @args.append library_mounts
54
+ end
55
+ end
@@ -0,0 +1,63 @@
1
+
2
+ require "bwrap/execution"
3
+ require "bwrap/output"
4
+ require_relative "args"
5
+
6
+ # Class to clean up namespace for implementation specific reasons.
7
+ #
8
+ # @api internal
9
+ class Bwrap::Args::Library
10
+ include Bwrap::Execution
11
+ include Bwrap::Output
12
+
13
+ # Used by {Bwrap::Args::Bind#libs_command_requires}.
14
+ def needed_libraries binary_paths
15
+ trace "Finding libraries #{binary_paths} requires"
16
+ @needed_libraries = []
17
+ # NOTE: This caching can be made more efficient, but need to look at it later, what to do about it.
18
+ @@needed_libraries_cache ||= []
19
+
20
+ output_format = "%F:libraries:%n"
21
+ scanelf_command = %W{ scanelf --nobanner --quiet --format #{output_format} --ldcache --needed }
22
+
23
+ if binary_paths.is_a? String
24
+ binary_paths = [ binary_paths ]
25
+ end
26
+
27
+ # Check if the exe is already resolved.
28
+ binary_paths.delete_if do |binary_path|
29
+ @@needed_libraries_cache.include? binary_path
30
+ end
31
+
32
+ return [] if binary_paths.empty?
33
+
34
+ data = execvalue(scanelf_command + binary_paths)
35
+ trace "scanelf found following libraries: #{data}"
36
+
37
+ lines = data.split "\n"
38
+ lines.each do |line|
39
+ parse_scanelf_line line
40
+ end
41
+
42
+ @needed_libraries
43
+ end
44
+
45
+ # Used by {#needed_libraries}.
46
+ private def parse_scanelf_line line
47
+ binary_path, libraries_line = line.split ":libraries:"
48
+ libraries = libraries_line.split ","
49
+
50
+ @needed_libraries += libraries
51
+
52
+ # Also check if requisite libraries needs some libraries.
53
+ inner = Bwrap::Args::Library.new
54
+ @needed_libraries += inner.needed_libraries libraries
55
+
56
+ # Mark library cached only after its dependencies have been also handled.
57
+ libraries.each do |library|
58
+ verb "Binding #{library} as dependency of #{binary_path}"
59
+ @@needed_libraries_cache << library
60
+ end
61
+ end
62
+ end
63
+ # class Library ended
@@ -24,7 +24,7 @@ class Bwrap::Args::MachineId
24
24
  # Returning [] means that execute() will ignore this fully.
25
25
  # Nil would be converted to empty string, causing spawn() to pass it as argument, causing
26
26
  # bwrap to misbehave.
27
- return [] unless @config.machine_id
27
+ return unless @config.machine_id
28
28
 
29
29
  machine_id = @config.machine_id
30
30
 
@@ -4,21 +4,29 @@ require_relative "args"
4
4
 
5
5
  # Bind arguments for bwrap.
6
6
  module Bwrap::Args::Mount
7
+ # Arguments for readwrite-binding {Config#root} as /.
8
+ private def root_mount
9
+ return unless @config.root
10
+
11
+ debug "Binding #{@config.root} as /"
12
+ @args.append %W{ --bind #{@config.root} / }
13
+ end
14
+
7
15
  # Arguments for mounting devtmpfs to /dev.
8
16
  private def dev_mount
9
17
  debug "Mounting new devtmpfs to /dev"
10
- %w{ --dev /dev }
18
+ @args.append %w{ --dev /dev }
11
19
  end
12
20
 
13
21
  # Arguments for mounting procfs to /proc.
14
22
  private def proc_mount
15
23
  debug "Mounting new procfs to /proc"
16
- %w{ --proc /proc }
24
+ @args.append %w{ --proc /proc }
17
25
  end
18
26
 
19
27
  # Arguments for mounting tmpfs to /tmp.
20
28
  private def tmp_as_tmpfs
21
29
  debug "Mounting tmpfs to /tmp"
22
- %w{ --tmpfs /tmp }
30
+ @args.append %w{ --tmpfs /tmp }
23
31
  end
24
32
  end
data/lib/bwrap/config.rb CHANGED
@@ -24,6 +24,9 @@ class Bwrap::Config
24
24
  # Given file as bound as /etc/machine_id.
25
25
  attr_accessor :machine_id
26
26
 
27
+ # Name of the user inside chroot.
28
+ #
29
+ # This is optional and defaults to no user.
27
30
  attr_accessor :user
28
31
 
29
32
  # Set to true to indicate we’re running a X.org application, meaning we need to do some extra holes,
@@ -32,11 +35,43 @@ class Bwrap::Config
32
35
  # @return [Boolean] Whether Xorg specific binds are used.
33
36
  attr_accessor :xorg_application
34
37
 
38
+ # Array of audio schemes usable inside chroot.
39
+ #
40
+ # Currently supports:
41
+ # - :pulseaudio
42
+ #
43
+ attr_accessor :audio
44
+
45
+ # @return [Boolean] true if network should be shared from host.
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.
50
+ #
51
+ # For now this just mounts all relevant files it can find.
52
+ #
53
+ # @return [Boolean] true if Linux library loaders are mounted inside chroot
54
+ attr_accessor :full_system_mounts
55
+
56
+ # Set to true if basic system directories, like /usr/lib and /usr/lib64,
57
+ # should be bound inside chroot.
58
+ #
59
+ # /usr/bin can be mounted using {Config#binaries_from=}.
60
+ #
61
+ # @return [Boolean] true if libdirs are mounted to the chroot
62
+ attr_accessor :libdir_mounts
63
+
35
64
  # Array of directories to be bind mounted and used to construct PATH environment variable.
36
65
  attr_reader :binaries_from
37
66
 
67
+ # TODO: Document this.
68
+ # TODO: I wonder if this should just be removed. I don’t know, this is a bit ...
69
+ # Well, I can see it can have some merit, but very hard to say.
38
70
  attr_reader :sandbox_directory
39
71
 
72
+ # Use given directory as root. End result is similar to classic chroot.
73
+ attr_reader :root
74
+
40
75
  # `Hash`[`Pathname`] => `Pathname` containing custom read-only binds.
41
76
  attr_reader :ro_binds
42
77
 
@@ -45,9 +80,62 @@ class Bwrap::Config
45
80
  # Defaults to Dir.tmpdir.
46
81
  attr_reader :tmpdir
47
82
 
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. I’ll look at it after I have an use for it.
104
+ def enable
105
+ @enabled = true
106
+ end
107
+
108
+ # Disable Ruby feature set.
109
+ def disable
110
+ @enabled = false
111
+ end
112
+
113
+ # Extra libraries to be loaded from `RbConfig::CONFIG["rubyarchdir"]`.
114
+ #
115
+ # @note This is only required to be called if extra dependencies are necessary.
116
+ # For example, psych.so requires libyaml.so.
117
+ def stdlib= libs
118
+ # Just a little check to have error earlier.
119
+ libs.each do |lib|
120
+ unless File.exist? "#{RbConfig::CONFIG["rubyarchdir"]}/#{lib}.so"
121
+ raise "Library “#{lib}” passed to Bwrap::Config::Ruby.stdlib= does not exist."
122
+ end
123
+ end
124
+
125
+ @stdlib = libs
126
+ end
127
+ end
128
+
129
+ # @return [Ruby] Instance of feature class for Ruby
130
+ def ruby
131
+ @ruby ||= Ruby.new
132
+ end
133
+ end
134
+
48
135
  def initialize
49
136
  @binaries_from = []
50
137
  @tmpdir = Dir.tmpdir
138
+ @audio = []
51
139
  end
52
140
 
53
141
  def binaries_from= array
@@ -61,6 +149,17 @@ class Bwrap::Config
61
149
  end
62
150
  end
63
151
 
152
+ # Enable or disable feature sets to control various aspects of sandboxing.
153
+ #
154
+ # @example To enable Ruby feature set
155
+ # @config.features.ruby = true
156
+ #
157
+ # @see {Features} List of available features
158
+ # @return [Features] Object used to toggle features
159
+ def features
160
+ @features ||= ::Bwrap::Config::Features.new
161
+ end
162
+
64
163
  def sandbox_directory= directory
65
164
  unless Dir.exist? directory
66
165
  raise "Given sandbox directory #{directory} does not exist. Please create it beforehand and setup to your needs."
@@ -69,6 +168,15 @@ class Bwrap::Config
69
168
  @sandbox_directory = directory
70
169
  end
71
170
 
171
+ # Directory used as writable root, akin to classic chroot.
172
+ def root= directory
173
+ unless Dir.exist? directory
174
+ raise "Given root directory #{directory} does not exist. Please create it beforehand and set up to your needs."
175
+ end
176
+
177
+ @root = directory
178
+ end
179
+
72
180
  # Set given hash of paths to be bound with --ro-bind.
73
181
  #
74
182
  # Key is source path, value is destination path.
data/lib/bwrap/version.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  # bwrap command runner tools.
4
4
  module Bwrap
5
5
  # Current version of bwrap.
6
- VERSION = "1.0.0-alpha3"
6
+ VERSION = "1.0.0-alpha4"
7
7
  end
8
8
 
9
9
  require "deep-cover" if ENV["DEEP_COVER"]
data/lib/bwrap.rb CHANGED
@@ -15,8 +15,13 @@ class Bwrap::Bwrap
15
15
 
16
16
  def initialize config
17
17
  @config = config
18
+ end
19
+
20
+ # Parses command line arguments given to caller script.
21
+ def parse_command_line_arguments
22
+ options = optimist_cli_args
18
23
 
19
- parse_command_line_arguments
24
+ Bwrap::Output.handle_output_options options
20
25
  end
21
26
 
22
27
  # Runs given command inside bwrap.
@@ -24,26 +29,20 @@ class Bwrap::Bwrap
24
29
  # @param command [String, Array] Command, with necessary arguments, to be executed inside bwrap
25
30
  def run command
26
31
  construct = Bwrap::Args::Construct.new
32
+ construct.command = command
27
33
  construct.config = @config
28
34
  bwrap_args = construct.construct_bwrap_args
29
35
 
30
36
  exec_command = [ "bwrap" ]
31
37
  exec_command += bwrap_args
32
- exec_command += %W{ #{command} --new-instance }
33
- exec_command += ARGV unless ARGV.empty?
38
+ exec_command.append command
39
+ exec_command += @cli_args if @cli_args
34
40
 
35
41
  execute exec_command
36
42
 
37
43
  construct.cleanup
38
44
  end
39
45
 
40
- # Parses command line arguments given to caller script.
41
- private def parse_command_line_arguments
42
- options = optimist_cli_args
43
-
44
- Bwrap::Output.handle_output_options options
45
- end
46
-
47
46
  # Parses global bwrap flags using Optimist.
48
47
  private def optimist_cli_args
49
48
  Optimist.options do
@@ -70,5 +69,7 @@ class Bwrap::Bwrap
70
69
 
71
70
  educate_on_error
72
71
  end
72
+
73
+ @cli_args = ARGV.dup
73
74
  end
74
75
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bwrap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre.alpha3
4
+ version: 1.0.0.pre.alpha4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samu Voutilainen
@@ -34,7 +34,7 @@ cert_chain:
34
34
  X4ioQwEn1/9tHs19VO1CLF58451HgEo1BXd7eWLmV1V5cqw0YWok1ly4L/Su/Phf
35
35
  MRxVMHiVAqY=
36
36
  -----END CERTIFICATE-----
37
- date: 2021-11-14 00:00:00.000000000 Z
37
+ date: 2021-11-22 00:00:00.000000000 Z
38
38
  dependencies:
39
39
  - !ruby/object:Gem::Dependency
40
40
  name: optimist
@@ -120,7 +120,8 @@ dependencies:
120
120
  - - "~>"
121
121
  - !ruby/object:Gem::Version
122
122
  version: '3.7'
123
- description: For now this just reserves this name. Please be back later.
123
+ description: For now this is tailored to my needs, so this may or may not be of any
124
+ use.
124
125
  email:
125
126
  - smar@smar.fi
126
127
  executables: []
@@ -135,6 +136,8 @@ files:
135
136
  - lib/bwrap/args/bind.rb
136
137
  - lib/bwrap/args/construct.rb
137
138
  - lib/bwrap/args/environment.rb
139
+ - lib/bwrap/args/features.rb
140
+ - lib/bwrap/args/library.rb
138
141
  - lib/bwrap/args/machine_id.rb
139
142
  - lib/bwrap/args/mount.rb
140
143
  - lib/bwrap/config.rb
@@ -174,5 +177,5 @@ rubyforge_project:
174
177
  rubygems_version: 2.7.6.3
175
178
  signing_key:
176
179
  specification_version: 4
177
- summary: 'THIS WILL BE IN FUTURE: Framework to create commands for bwrap'
180
+ summary: Framework to create commands for bwrap
178
181
  test_files: []
metadata.gz.sig CHANGED
Binary file