bwrap 1.0.0.pre.alpha1 → 1.0.0.pre.alpha5
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 +30 -0
- data/README.md +2 -0
- data/lib/bwrap/args/bind.rb +150 -25
- data/lib/bwrap/args/construct.rb +72 -35
- data/lib/bwrap/args/features.rb +66 -0
- data/lib/bwrap/args/library.rb +130 -0
- data/lib/bwrap/args/machine_id.rb +1 -1
- data/lib/bwrap/args/mount.rb +11 -3
- data/lib/bwrap/config.rb +115 -0
- data/lib/bwrap/execution/execute.rb +1 -1
- data/lib/bwrap/execution/path.rb +64 -0
- data/lib/bwrap/execution.rb +15 -27
- data/lib/bwrap/output/log.rb +3 -3
- data/lib/bwrap/output.rb +8 -4
- data/lib/bwrap/version.rb +2 -2
- data/lib/bwrap.rb +19 -12
- data.tar.gz.sig +0 -0
- metadata +15 -9
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dfb5f9bdbcf68df6068aebca204e72ef9272829b1f8db11c34e5a4da469cc2c7
|
4
|
+
data.tar.gz: 5f19c25ecad9b7f4923f80a6d61c87c6382671667f6b39eed0198befbb8eccd2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9682aff2b43180fee0e8d7b2b7234d4bb516e86c85dcabc5b40a1047284f9f5bf9e0641dff80483e4645b8aa4bd06c9b9de8ba1b43cd78af3b77de1060c8ad6
|
7
|
+
data.tar.gz: cadd731077ff175b86cf0d56f17dd1c2cb3123e5d9b1dcff17156da5d706d7da12274bc59297ae925c1f07ea5b3a325c999c942048c2c5b165755934ae16d2f8
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,37 @@
|
|
1
1
|
# Changes
|
2
2
|
|
3
|
+
## 1.0.0-alpha5 (29.11.2021)
|
4
|
+
|
5
|
+
* Execution#command_available?: support absolute paths
|
6
|
+
* Execution#which: support absolute paths
|
7
|
+
* Many miscellaneous fixes
|
8
|
+
|
9
|
+
## 1.0.0-alpha4 (22.11.2021)
|
10
|
+
|
11
|
+
* Allow use without home directory set
|
12
|
+
* Bwrap#parse_command_line_arguments is no longer run when Bwrap is initialized
|
13
|
+
* Made pulseaudio optional
|
14
|
+
* Changed --share-net to be added only if requested
|
15
|
+
* Added Config#root= to specify path used as writable root
|
16
|
+
* Added Config#full_system_mounts to control whether library loaders are mounted inside chroot
|
17
|
+
* Added Config#libdir_mounts
|
18
|
+
* Added Config#features
|
19
|
+
|
20
|
+
## 1.0.0-alpha3 (14.11.2021)
|
21
|
+
|
22
|
+
* Avoid frozen string literal modification
|
23
|
+
|
24
|
+
## 1.0.0-alpha2 (14.11.2021)
|
25
|
+
|
26
|
+
* Made gem to tell its license (ISC)
|
27
|
+
* Gem building now allows newer bundler versions than 1.17
|
28
|
+
* Added Config#xorg_application option
|
29
|
+
* Properly resolve /etc/resolv.conf
|
30
|
+
|
3
31
|
## 1.0.0-alpha1 (10.11.2021)
|
4
32
|
|
33
|
+
* First working version
|
34
|
+
|
5
35
|
## 0.1.0 (unreleased)
|
6
36
|
|
7
37
|
* First, currently unfinished and unreleased version. Work in Progress.
|
data/README.md
CHANGED
@@ -31,3 +31,5 @@ Please see [API documentation](https://www.rubydoc.info/gems/bwrap) for usage in
|
|
31
31
|
## Contributing
|
32
32
|
|
33
33
|
Bug reports and pull requests are welcome at https://git.sr.ht/~smar/ruby-bwrap.
|
34
|
+
|
35
|
+
Gerrit instance https://gerrit.smar.fi/admin/repos/ruby-bwrap can also be used.
|
data/lib/bwrap/args/bind.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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,58 @@ 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
|
61
|
-
"#{
|
150
|
+
debug "Using following libdir mounts:\n" \
|
151
|
+
"#{libdir_mounts}\n" \
|
62
152
|
"(Odd is key, even is value)"
|
63
153
|
end
|
64
|
-
|
154
|
+
|
155
|
+
@args.append libdir_mounts
|
65
156
|
end
|
66
157
|
|
67
|
-
#
|
68
|
-
private def
|
69
|
-
|
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
|
-
|
72
|
-
|
73
|
-
|
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
|
177
|
+
# full_system_mounts option.)
|
178
|
+
private def libs_command_requires
|
179
|
+
executable_name = @command.is_a?(String) && @command || @command[0]
|
180
|
+
executable_path = which executable_name
|
181
|
+
|
182
|
+
# TODO: Put this behind additional flag for extra control/sanity.
|
183
|
+
# Some executables are shell scripts and similar. For them we need to use the interpreter.
|
184
|
+
|
185
|
+
mime = Mime.new executable_name, executable_path
|
186
|
+
return unless mime.resolve_mime_type
|
187
|
+
|
188
|
+
# Then find out required libraries
|
189
|
+
|
190
|
+
library_mounts = []
|
191
|
+
|
192
|
+
library_object = Bwrap::Args::Library.new
|
193
|
+
libraries = library_object.libraries_needed_by mime.executable_path
|
194
|
+
|
195
|
+
# TODO: following is bad?
|
196
|
+
#library_object.needed_libraries(mime.executable_path).each do |library|
|
197
|
+
libraries.each do |library|
|
198
|
+
library_mounts << "--ro-bind" << library << library
|
74
199
|
end
|
75
200
|
|
76
|
-
|
201
|
+
@args.append library_mounts
|
77
202
|
end
|
78
|
-
end
|
203
|
+
end
|
data/lib/bwrap/args/construct.rb
CHANGED
@@ -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
|
-
@
|
22
|
-
|
23
|
-
@machine_id = Bwrap::Args::MachineId.new
|
24
|
-
@machine_id.config = @config
|
30
|
+
@args = []
|
31
|
+
create_objects
|
25
32
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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,37 +62,64 @@ 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
|
86
|
+
return unless @config.xorg_application
|
87
|
+
|
57
88
|
xauth_args = %W{ --ro-bind #{Dir.home}/.Xauthority #{Dir.home}/.Xauthority }
|
58
89
|
debug "Binding following .Xauthority file: #{Dir.home}/.Xauthority"
|
59
|
-
xauth_args
|
90
|
+
@args.append xauth_args
|
60
91
|
end
|
61
92
|
|
62
93
|
# Arguments to read-only bind /etc/resolv.conf.
|
63
94
|
private def resolv_conf
|
64
|
-
#
|
65
|
-
source_resolv_conf = "/
|
95
|
+
# We can’t really bind symlinks, so let’s resolve real path to resolv.conf, in case it is symlinked.
|
96
|
+
source_resolv_conf = Pathname.new "/etc/resolv.conf"
|
97
|
+
source_resolv_conf = source_resolv_conf.realpath
|
98
|
+
|
66
99
|
debug "Binding #{source_resolv_conf} as /etc/resolv.conf"
|
67
|
-
%
|
100
|
+
@args.append %W{ --ro-bind #{source_resolv_conf} /etc/resolv.conf }
|
68
101
|
end
|
69
102
|
|
70
103
|
# Arguments to create `/run/user/#{uid}`.
|
71
104
|
private def create_user_dir
|
72
105
|
trace "Creating directory /run/user/#{uid}"
|
73
|
-
%W{ --dir /run/user/#{uid} }
|
106
|
+
@args.append %W{ --dir /run/user/#{uid} }
|
74
107
|
end
|
75
108
|
|
76
109
|
# Arguments to bind necessary pulseaudio data for audio support.
|
77
110
|
private def read_only_pulseaudio
|
111
|
+
return unless @config.audio.include? :pulseaudio
|
112
|
+
|
78
113
|
debug "Binding pulseaudio"
|
79
|
-
%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 }
|
80
115
|
end
|
81
116
|
|
82
117
|
# Arguments to allow network connection inside sandbox.
|
83
118
|
private def share_net
|
119
|
+
return unless @config.share_net
|
120
|
+
|
84
121
|
verb "Sharing network"
|
85
|
-
%w{ --share-net }
|
122
|
+
@args.append %w{ --share-net }
|
86
123
|
end
|
87
124
|
|
88
125
|
# Arguments to set hostname to whatever is configured.
|
@@ -90,7 +127,7 @@ class Bwrap::Args::Construct
|
|
90
127
|
return unless @config.hostname
|
91
128
|
|
92
129
|
debug "Setting hostname to #{@config.hostname}"
|
93
|
-
%W{ --hostname #{@config.hostname} }
|
130
|
+
@args.append %W{ --hostname #{@config.hostname} }
|
94
131
|
end
|
95
132
|
|
96
133
|
# Returns current user id.
|
@@ -0,0 +1,66 @@
|
|
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
|
+
# @api internal
|
14
|
+
class RubyBinds
|
15
|
+
attr_reader :mounts
|
16
|
+
|
17
|
+
# Bind system paths so scripts works inside sandbox.
|
18
|
+
def sitedir_mounts
|
19
|
+
mounts = []
|
20
|
+
mounts << "--ro-bind" << RbConfig::CONFIG["sitedir"] << RbConfig::CONFIG["sitedir"]
|
21
|
+
mounts << "--ro-bind" << RbConfig::CONFIG["rubyhdrdir"] << RbConfig::CONFIG["rubyhdrdir"]
|
22
|
+
mounts << "--ro-bind" << RbConfig::CONFIG["rubylibdir"] << RbConfig::CONFIG["rubylibdir"]
|
23
|
+
mounts << "--ro-bind" << RbConfig::CONFIG["vendordir"] << RbConfig::CONFIG["vendordir"]
|
24
|
+
|
25
|
+
mounts
|
26
|
+
end
|
27
|
+
|
28
|
+
# Create binds for required system libraries.
|
29
|
+
#
|
30
|
+
# These are in path like /usr/lib64/ruby/2.5.0/x86_64-linux-gnu/,
|
31
|
+
# and as they are mostly shared libraries, they may have some extra
|
32
|
+
# dependencies that also need to be bound inside the sandbox.
|
33
|
+
def stdlib_mounts stdlib
|
34
|
+
library_mounts = []
|
35
|
+
library = Bwrap::Args::Library.new
|
36
|
+
stdlib.each do |lib|
|
37
|
+
path = "#{RbConfig::CONFIG["rubyarchdir"]}/#{lib}.so"
|
38
|
+
|
39
|
+
library.needed_libraries(path).each do |requisite_library|
|
40
|
+
library_mounts << "--ro-bind" << requisite_library << requisite_library
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# {Array} of parameters passed to bwrap.
|
47
|
+
attr_writer :args
|
48
|
+
|
49
|
+
# Instance of {Config}.
|
50
|
+
attr_writer :config
|
51
|
+
|
52
|
+
def feature_binds
|
53
|
+
ruby_binds
|
54
|
+
end
|
55
|
+
|
56
|
+
# @note This does not allow development headers needed for compilation for now.
|
57
|
+
# I’ll look at it after I have an use for it.
|
58
|
+
private def ruby_binds
|
59
|
+
return unless @config.features.ruby.enabled?
|
60
|
+
|
61
|
+
binds = RubyBinds.new
|
62
|
+
|
63
|
+
@args.append binds.sitedir_mounts
|
64
|
+
@args.append binds.stdlib_mounts @config.features.ruby.stdlib
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bwrap/execution"
|
4
|
+
require "bwrap/output"
|
5
|
+
require_relative "args"
|
6
|
+
|
7
|
+
# Class to clean up namespace for implementation specific reasons.
|
8
|
+
#
|
9
|
+
# @api internal
|
10
|
+
class Bwrap::Args::Library
|
11
|
+
include Bwrap::Execution
|
12
|
+
include Bwrap::Output
|
13
|
+
|
14
|
+
# NOTE: This caching can be made more efficient, but need to look at it later, what to do about it.
|
15
|
+
@@needed_libraries_cache ||= []
|
16
|
+
|
17
|
+
# Otherwise similar to {#needed_libraries}, but checks used libc to handle musl executables.
|
18
|
+
#
|
19
|
+
# @param executable [String] Path to the executable to find dependencies for
|
20
|
+
def libraries_needed_by executable
|
21
|
+
# %i == interpreter, the library used to load the executable by kernel.
|
22
|
+
# %F == Path to given file.
|
23
|
+
output_format = "%i::SEPARATOR::%F"
|
24
|
+
scanelf_command = %W{ scanelf --nobanner --quiet --format #{output_format} }
|
25
|
+
scanelf_command << executable
|
26
|
+
|
27
|
+
data = execvalue scanelf_command
|
28
|
+
data = data.strip
|
29
|
+
interpreter, _executable_path = data.split "::SEPARATOR::"
|
30
|
+
interpreter = Pathname.new interpreter
|
31
|
+
|
32
|
+
if interpreter.basename.to_s[0..6] == "ld-musl"
|
33
|
+
musl_needed_libraries executable
|
34
|
+
else
|
35
|
+
# For glibc, scanelf can return full paths for us most of time.
|
36
|
+
needed_libraries executable
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# @param binary_paths [String, Array] one or more paths to be resolved
|
41
|
+
#
|
42
|
+
# @todo Maybe caching should be done here too?
|
43
|
+
def musl_needed_libraries binary_paths
|
44
|
+
trace "Finding musl libraries #{binary_paths} requires"
|
45
|
+
@needed_libraries = []
|
46
|
+
|
47
|
+
if binary_paths.is_a? String
|
48
|
+
binary_paths = [ binary_paths ]
|
49
|
+
end
|
50
|
+
|
51
|
+
binary_paths.each do |binary_path|
|
52
|
+
output = execvalue %W{ ldd #{binary_path} }
|
53
|
+
lines = output.split "\n"
|
54
|
+
_interpreter_line = lines.shift
|
55
|
+
|
56
|
+
lines.each do |line|
|
57
|
+
parse_ldd_line line
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
@needed_libraries
|
62
|
+
end
|
63
|
+
|
64
|
+
# Used by {Bwrap::Args::Bind#libs_command_requires}.
|
65
|
+
#
|
66
|
+
# @param binary_paths [String, Array] one or more paths to be resolved
|
67
|
+
def needed_libraries binary_paths
|
68
|
+
trace "Finding libraries #{binary_paths} requires"
|
69
|
+
@needed_libraries = []
|
70
|
+
|
71
|
+
# %i == interpreter, the library used to load the executable by kernel.
|
72
|
+
output_format = "%F::SEPARATOR::%n"
|
73
|
+
scanelf_command = %W{ scanelf --nobanner --quiet --format #{output_format} --ldcache --needed }
|
74
|
+
|
75
|
+
if binary_paths.is_a? String
|
76
|
+
binary_paths = [ binary_paths ]
|
77
|
+
end
|
78
|
+
|
79
|
+
# Check if the exe is already resolved.
|
80
|
+
binary_paths.delete_if do |binary_path|
|
81
|
+
@@needed_libraries_cache.include? binary_path
|
82
|
+
end
|
83
|
+
|
84
|
+
return [] if binary_paths.empty?
|
85
|
+
|
86
|
+
data = execvalue(scanelf_command + binary_paths)
|
87
|
+
trace "scanelf found following libraries: #{data}"
|
88
|
+
|
89
|
+
lines = data.split "\n"
|
90
|
+
lines.each do |line|
|
91
|
+
parse_scanelf_line line
|
92
|
+
end
|
93
|
+
|
94
|
+
@needed_libraries
|
95
|
+
end
|
96
|
+
|
97
|
+
# Used by {#needed_libraries}.
|
98
|
+
private def parse_scanelf_line line
|
99
|
+
binary_path, libraries_line = line.split "::SEPARATOR::"
|
100
|
+
libraries = libraries_line.split ","
|
101
|
+
|
102
|
+
@needed_libraries += libraries
|
103
|
+
|
104
|
+
# Also check if requisite libraries needs some libraries.
|
105
|
+
inner = Bwrap::Args::Library.new
|
106
|
+
@needed_libraries += inner.needed_libraries libraries
|
107
|
+
|
108
|
+
# Mark library cached only after its dependencies have been also handled.
|
109
|
+
libraries.each do |library|
|
110
|
+
verb "Binding #{library} as dependency of #{binary_path}"
|
111
|
+
@@needed_libraries_cache << library
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Used by {#musl_needed_libraries}.
|
116
|
+
private def parse_ldd_line line
|
117
|
+
line = line.strip
|
118
|
+
_library_name, library_data = line.split " => "
|
119
|
+
|
120
|
+
matches = library_data.match(/(.*) \(0x[0-9a-f]+\)/)
|
121
|
+
library_path = matches[1]
|
122
|
+
|
123
|
+
@needed_libraries << library_path
|
124
|
+
|
125
|
+
# Also check if requisite libraries needs some libraries.
|
126
|
+
inner = Bwrap::Args::Library.new
|
127
|
+
@needed_libraries += inner.musl_needed_libraries library_path
|
128
|
+
end
|
129
|
+
end
|
130
|
+
# 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
|
27
|
+
return unless @config.machine_id
|
28
28
|
|
29
29
|
machine_id = @config.machine_id
|
30
30
|
|
data/lib/bwrap/args/mount.rb
CHANGED
@@ -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,13 +24,54 @@ 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
|
|
32
|
+
# Set to true to indicate we’re running a X.org application, meaning we need to do some extra holes,
|
33
|
+
# like binding .Xauthority.
|
34
|
+
#
|
35
|
+
# @return [Boolean] Whether Xorg specific binds are used.
|
36
|
+
attr_accessor :xorg_application
|
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
|
+
|
29
64
|
# Array of directories to be bind mounted and used to construct PATH environment variable.
|
30
65
|
attr_reader :binaries_from
|
31
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.
|
32
70
|
attr_reader :sandbox_directory
|
33
71
|
|
72
|
+
# Use given directory as root. End result is similar to classic chroot.
|
73
|
+
attr_reader :root
|
74
|
+
|
34
75
|
# `Hash`[`Pathname`] => `Pathname` containing custom read-only binds.
|
35
76
|
attr_reader :ro_binds
|
36
77
|
|
@@ -39,9 +80,63 @@ class Bwrap::Config
|
|
39
80
|
# Defaults to Dir.tmpdir.
|
40
81
|
attr_reader :tmpdir
|
41
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.
|
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
|
+
|
42
136
|
def initialize
|
43
137
|
@binaries_from = []
|
44
138
|
@tmpdir = Dir.tmpdir
|
139
|
+
@audio = []
|
45
140
|
end
|
46
141
|
|
47
142
|
def binaries_from= array
|
@@ -55,6 +150,17 @@ class Bwrap::Config
|
|
55
150
|
end
|
56
151
|
end
|
57
152
|
|
153
|
+
# Enable or disable feature sets to control various aspects of sandboxing.
|
154
|
+
#
|
155
|
+
# @example To enable Ruby feature set
|
156
|
+
# @config.features.ruby = true
|
157
|
+
#
|
158
|
+
# @see {Features} List of available features
|
159
|
+
# @return [Features] Object used to toggle features
|
160
|
+
def features
|
161
|
+
@features ||= ::Bwrap::Config::Features.new
|
162
|
+
end
|
163
|
+
|
58
164
|
def sandbox_directory= directory
|
59
165
|
unless Dir.exist? directory
|
60
166
|
raise "Given sandbox directory #{directory} does not exist. Please create it beforehand and setup to your needs."
|
@@ -63,6 +169,15 @@ class Bwrap::Config
|
|
63
169
|
@sandbox_directory = directory
|
64
170
|
end
|
65
171
|
|
172
|
+
# Directory used as writable root, akin to classic chroot.
|
173
|
+
def root= directory
|
174
|
+
unless Dir.exist? directory
|
175
|
+
raise "Given root directory #{directory} does not exist. Please create it beforehand and set up to your needs."
|
176
|
+
end
|
177
|
+
|
178
|
+
@root = directory
|
179
|
+
end
|
180
|
+
|
66
181
|
# Set given hash of paths to be bound with --ro-bind.
|
67
182
|
#
|
68
183
|
# Key is source path, value is destination path.
|
@@ -95,7 +95,7 @@ class Bwrap::Execution::Execute
|
|
95
95
|
# Stub to instruct implementation in subclass.
|
96
96
|
def self.prepend_rootcmd command, rootcmd:
|
97
97
|
raise NotImplementedError, "If rootcmd execution is necessary, monkey patch Bwrap::Execution::Execute " \
|
98
|
-
|
98
|
+
"to add “self.prepend_rootcmd(command, rootcmd:)” method."
|
99
99
|
end
|
100
100
|
|
101
101
|
# Used by `#handle_logging`.
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bwrap/output"
|
4
|
+
|
5
|
+
# Path checking methods.
|
6
|
+
module Bwrap::Execution::Path
|
7
|
+
# @api internal
|
8
|
+
class Environment
|
9
|
+
def self.each_env_path command
|
10
|
+
exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [ "" ]
|
11
|
+
|
12
|
+
ENV["PATH"].split(File::PATH_SEPARATOR).each do |env_path|
|
13
|
+
exts.each do |ext|
|
14
|
+
exe = File.join(env_path, "#{command}#{ext}")
|
15
|
+
yield exe
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Check if requested program can be found.
|
22
|
+
#
|
23
|
+
# Should work cross-platform and in restricted environents pretty well.
|
24
|
+
private def command_available? command
|
25
|
+
# Special handling for absolute paths.
|
26
|
+
path = Pathname.new command
|
27
|
+
if path.absolute?
|
28
|
+
if path.executable? && !path.directory?
|
29
|
+
return true
|
30
|
+
end
|
31
|
+
|
32
|
+
return false
|
33
|
+
end
|
34
|
+
|
35
|
+
Bwrap::Execution::Path::Environment.each_env_path command do |exe|
|
36
|
+
return true if File.executable?(exe) && !File.directory?(exe)
|
37
|
+
end
|
38
|
+
|
39
|
+
false
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns path to given executable.
|
43
|
+
private def which command, fail: true
|
44
|
+
# Special handling for absolute paths.
|
45
|
+
path = Pathname.new command
|
46
|
+
if path.absolute?
|
47
|
+
if path.executable?
|
48
|
+
return command
|
49
|
+
end
|
50
|
+
|
51
|
+
raise CommandNotFound.new command: command if fail
|
52
|
+
|
53
|
+
return nil
|
54
|
+
end
|
55
|
+
|
56
|
+
Bwrap::Execution::Path::Environment.each_env_path command do |exe|
|
57
|
+
return exe if File.executable?(exe) && !File.directory?(exe)
|
58
|
+
end
|
59
|
+
|
60
|
+
return nil unless fail
|
61
|
+
|
62
|
+
raise CommandNotFound.new command: command
|
63
|
+
end
|
64
|
+
end
|
data/lib/bwrap/execution.rb
CHANGED
@@ -3,12 +3,14 @@
|
|
3
3
|
require "bwrap/version"
|
4
4
|
require "bwrap/output"
|
5
5
|
require_relative "execution/execute"
|
6
|
+
require_relative "execution/path"
|
6
7
|
|
7
8
|
# @abstract Module to be included in a class that needs to execute commands.
|
8
9
|
#
|
9
10
|
# Methods to execute processes.
|
10
11
|
module Bwrap::Execution
|
11
12
|
include Bwrap::Output
|
13
|
+
include Bwrap::Execution::Path
|
12
14
|
|
13
15
|
# Unspecified execution related error.
|
14
16
|
class CommandError < StandardError
|
@@ -18,6 +20,19 @@ module Bwrap::Execution
|
|
18
20
|
class ExecutionFailed < CommandError
|
19
21
|
end
|
20
22
|
|
23
|
+
# Thrown if given command was not found.
|
24
|
+
class CommandNotFound < CommandError
|
25
|
+
# Command that was looked at.
|
26
|
+
attr_reader :command
|
27
|
+
|
28
|
+
def initialize command:
|
29
|
+
@command = command
|
30
|
+
msg = "Failed to find #{command} from PATH."
|
31
|
+
|
32
|
+
super msg
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
21
36
|
# Actual implementation of execution command. Can be used when static method is needed.
|
22
37
|
#
|
23
38
|
# @note When an array is given as a command, empty strings are passed as empty arguments.
|
@@ -83,33 +98,6 @@ module Bwrap::Execution
|
|
83
98
|
@last_status
|
84
99
|
end
|
85
100
|
|
86
|
-
# Check if requested program can be found.
|
87
|
-
#
|
88
|
-
# Should work cross-platform and in restricted environents pretty well.
|
89
|
-
private def command_available? command
|
90
|
-
exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [ "" ]
|
91
|
-
ENV["PATH"].split(File::PATH_SEPARATOR).each do |path|
|
92
|
-
exts.each do |ext|
|
93
|
-
exe = File.join(path, "#{command}#{ext}")
|
94
|
-
return true if File.executable?(exe) && !File.directory?(exe)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
false
|
98
|
-
end
|
99
|
-
|
100
|
-
# Returns path to given executable.
|
101
|
-
private def which command, fail: true
|
102
|
-
exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [ "" ]
|
103
|
-
ENV["PATH"].split(File::PATH_SEPARATOR).each do |path|
|
104
|
-
exts.each do |ext|
|
105
|
-
exe = File.join(path, "#{command}#{ext}")
|
106
|
-
return exe if File.executable?(exe) && !File.directory?(exe)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
error "Failed to find #{command} from PATH." if fail
|
110
|
-
nil
|
111
|
-
end
|
112
|
-
|
113
101
|
# Execute a command.
|
114
102
|
#
|
115
103
|
# This method can be used by including Execution module in a class that should be able to
|
data/lib/bwrap/output/log.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# frozen_string_literal:
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# force_encoding modifies string, so can’t freeze strings.
|
4
4
|
|
@@ -15,12 +15,12 @@ class Bwrap::Output::Log
|
|
15
15
|
|
16
16
|
# Writes given string to log.
|
17
17
|
def self.write_to_log str
|
18
|
-
@@log_file&.write str.force_encoding("UTF-8")
|
18
|
+
@@log_file&.write str.dup.force_encoding("UTF-8")
|
19
19
|
end
|
20
20
|
|
21
21
|
# Writes given string to log.
|
22
22
|
def self.puts_to_log str
|
23
|
-
@@log_file&.puts str.force_encoding("UTF-8")
|
23
|
+
@@log_file&.puts str.dup.force_encoding("UTF-8")
|
24
24
|
end
|
25
25
|
|
26
26
|
# Closes an open log file.
|
data/lib/bwrap/output.rb
CHANGED
@@ -81,13 +81,16 @@ module Bwrap::Output
|
|
81
81
|
# Aborts current process.
|
82
82
|
#
|
83
83
|
# Use this instead of Ruby’s #exit in order to filter out dummy #exit calls from the code.
|
84
|
-
def self.error_output str = nil, label: :unspecified, log_callback: 1
|
84
|
+
def self.error_output str = nil, label: :unspecified, log_callback: 1, raise_exception: false
|
85
85
|
unless str.nil?
|
86
86
|
out = Bwrap::Output::Levels.error_print_formatted str, log_callback: (log_callback + 1)
|
87
87
|
Bwrap::Output::Log.puts_to_log out
|
88
88
|
end
|
89
89
|
|
90
|
-
|
90
|
+
exit_code = Bwrap::Execution::Labels.resolve_exit_code(label)
|
91
|
+
raise str if raise_exception
|
92
|
+
|
93
|
+
exit exit_code
|
91
94
|
end
|
92
95
|
|
93
96
|
# @return true if --verbose, --debug or --trace has been passed, false if not.
|
@@ -147,7 +150,8 @@ module Bwrap::Output
|
|
147
150
|
#
|
148
151
|
# @param str String to be outputted
|
149
152
|
# @param label [Symbol] Exit label accepted by {Bwrap::Execution.resolve_exit_code}
|
150
|
-
|
151
|
-
|
153
|
+
# @param raise [Boolean] if true, an exception is raised instead of just existing with exit code.
|
154
|
+
private def error str = nil, label: :unspecified, raise_exception: false
|
155
|
+
Bwrap::Output.error_output(str, label: label, log_callback: 2, raise_exception: raise_exception)
|
152
156
|
end
|
153
157
|
end
|
data/lib/bwrap/version.rb
CHANGED
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 = parse_options
|
18
23
|
|
19
|
-
|
24
|
+
Bwrap::Output.handle_output_options options
|
20
25
|
end
|
21
26
|
|
22
27
|
# Runs given command inside bwrap.
|
@@ -24,29 +29,27 @@ 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
|
33
|
-
exec_command +=
|
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
|
-
|
49
|
-
|
47
|
+
#
|
48
|
+
# Sets instance variable `@cli_args`.
|
49
|
+
#
|
50
|
+
# @return [Hash] options parsed by {Optimist.options}
|
51
|
+
private def parse_options
|
52
|
+
options = Optimist.options do
|
50
53
|
version ::Bwrap::VERSION
|
51
54
|
|
52
55
|
banner "Usage:"
|
@@ -70,5 +73,9 @@ class Bwrap::Bwrap
|
|
70
73
|
|
71
74
|
educate_on_error
|
72
75
|
end
|
76
|
+
|
77
|
+
@cli_args = ARGV.dup
|
78
|
+
|
79
|
+
options
|
73
80
|
end
|
74
81
|
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.
|
4
|
+
version: 1.0.0.pre.alpha5
|
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-
|
37
|
+
date: 2021-11-29 00:00:00.000000000 Z
|
38
38
|
dependencies:
|
39
39
|
- !ruby/object:Gem::Dependency
|
40
40
|
name: optimist
|
@@ -54,16 +54,16 @@ dependencies:
|
|
54
54
|
name: bundler
|
55
55
|
requirement: !ruby/object:Gem::Requirement
|
56
56
|
requirements:
|
57
|
-
- - "
|
57
|
+
- - ">="
|
58
58
|
- !ruby/object:Gem::Version
|
59
|
-
version: '1.
|
59
|
+
version: '1.16'
|
60
60
|
type: :development
|
61
61
|
prerelease: false
|
62
62
|
version_requirements: !ruby/object:Gem::Requirement
|
63
63
|
requirements:
|
64
|
-
- - "
|
64
|
+
- - ">="
|
65
65
|
- !ruby/object:Gem::Version
|
66
|
-
version: '1.
|
66
|
+
version: '1.16'
|
67
67
|
- !ruby/object:Gem::Dependency
|
68
68
|
name: rake
|
69
69
|
requirement: !ruby/object:Gem::Requirement
|
@@ -120,7 +120,8 @@ dependencies:
|
|
120
120
|
- - "~>"
|
121
121
|
- !ruby/object:Gem::Version
|
122
122
|
version: '3.7'
|
123
|
-
description: For now this
|
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
|
@@ -142,6 +145,7 @@ files:
|
|
142
145
|
- lib/bwrap/execution/execute.rb
|
143
146
|
- lib/bwrap/execution/execution.rb
|
144
147
|
- lib/bwrap/execution/labels.rb
|
148
|
+
- lib/bwrap/execution/path.rb
|
145
149
|
- lib/bwrap/output.rb
|
146
150
|
- lib/bwrap/output/colors.rb
|
147
151
|
- lib/bwrap/output/levels.rb
|
@@ -149,11 +153,13 @@ files:
|
|
149
153
|
- lib/bwrap/output/output.rb
|
150
154
|
- lib/bwrap/version.rb
|
151
155
|
homepage: https://git.sr.ht/~smar/ruby-bwrap
|
152
|
-
licenses:
|
156
|
+
licenses:
|
157
|
+
- ISC
|
153
158
|
metadata:
|
154
159
|
homepage_uri: https://git.sr.ht/~smar/ruby-bwrap
|
155
160
|
source_code_uri: https://git.sr.ht/~smar/ruby-bwrap
|
156
161
|
changelog_uri: https://git.sr.ht/~smar/ruby-bwrap/tree/master/item/CHANGELOG.md
|
162
|
+
rubygems_mfa_required: 'false'
|
157
163
|
post_install_message:
|
158
164
|
rdoc_options: []
|
159
165
|
require_paths:
|
@@ -173,5 +179,5 @@ rubyforge_project:
|
|
173
179
|
rubygems_version: 2.7.6.3
|
174
180
|
signing_key:
|
175
181
|
specification_version: 4
|
176
|
-
summary:
|
182
|
+
summary: Framework to create commands for bwrap
|
177
183
|
test_files: []
|
metadata.gz.sig
CHANGED
Binary file
|