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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +11 -0
- data/lib/bwrap/args/bind.rb +146 -25
- data/lib/bwrap/args/construct.rb +68 -35
- data/lib/bwrap/args/features.rb +55 -0
- data/lib/bwrap/args/library.rb +63 -0
- data/lib/bwrap/args/machine_id.rb +1 -1
- data/lib/bwrap/args/mount.rb +11 -3
- data/lib/bwrap/config.rb +108 -0
- data/lib/bwrap/version.rb +1 -1
- data/lib/bwrap.rb +11 -10
- data.tar.gz.sig +0 -0
- metadata +7 -4
- 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: 5101d7848dccd6da3f68fc02f08b37ec1cfadc516b45cb964265a3f0a60e8ea3
|
4
|
+
data.tar.gz: 6dbf98ccc5faba3385ce8fe6f9890f9e7369860531e4161c8092611c18a8ca02
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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,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
|
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 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
|
-
|
196
|
+
@args.append library_mounts
|
77
197
|
end
|
78
|
-
|
198
|
+
|
199
|
+
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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
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
|
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,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
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
|
-
|
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
|
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
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.
|
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-
|
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
|
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:
|
180
|
+
summary: Framework to create commands for bwrap
|
178
181
|
test_files: []
|
metadata.gz.sig
CHANGED
Binary file
|