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

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 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