bwrap 1.2.0 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +14 -0
- data/README.md +9 -0
- data/lib/bwrap/args/bind.rb +0 -4
- data/lib/bwrap/args/construct.rb +5 -1
- data/lib/bwrap/args/namespace.rb +25 -0
- data/lib/bwrap/args/network.rb +5 -0
- data/lib/bwrap/bwrap.rb +3 -1
- data/lib/bwrap/config.rb +18 -2
- data/lib/bwrap/exceptions.rb +1 -0
- data/lib/bwrap/execution.rb +1 -0
- data/lib/bwrap/resolvers/library/base.rb +22 -0
- data/lib/bwrap/resolvers/library/library.rb +74 -0
- data/lib/bwrap/resolvers/library/llvm_readelf.rb +133 -0
- data/lib/bwrap/resolvers/library/musl.rb +54 -0
- data/lib/bwrap/resolvers/library.rb +3 -151
- data/lib/bwrap/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +21 -16
- 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: 2d50d32e5158e20f7a5a1f75124c8b657a12b54b3392612d5aa11e9717add289
|
4
|
+
data.tar.gz: 7ac4aede1519880cd7c4e48d233688d1fb0d2ade75e8dc202bd27969d9c28428
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 88dfdab0abd2342289724060107c1a8fcc681eac5a4b24f402e316cc8d4470e33cb9fe11f7be1072b2dc0b97f3b1fc10e7df92bce192f0de9de9978f423237c0
|
7
|
+
data.tar.gz: 76fc0bd2dc04e98b3254a540813212a6b9fb7cba1b7c0f64f49a19577106eb0dc8efac79215e4f689a229e1bfce57e9b9ca0926347d552d28000aa815697892f
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# Changes
|
2
2
|
|
3
|
+
## 1.3.1 (06.01.2023)
|
4
|
+
|
5
|
+
* Renewed expired key
|
6
|
+
|
7
|
+
## 1.3.0 (06.01.2023)
|
8
|
+
|
9
|
+
NOTE: No gem was released due expired key.
|
10
|
+
|
11
|
+
* Introduced llvm-readelf as additional dependency for library resolution.
|
12
|
+
* Fix library resolution on newer systems.
|
13
|
+
* Made resolv.conf binding to require a configuration option.
|
14
|
+
* Added option for --unshare-all (enabled by default, which is previous behaviour).
|
15
|
+
* Return output of the command with Bwrap#run
|
16
|
+
|
3
17
|
## 1.2.0 (20.07.2022)
|
4
18
|
|
5
19
|
* Properly throw execution failure exception
|
data/README.md
CHANGED
@@ -20,6 +20,15 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
$ gem install bwrap
|
22
22
|
|
23
|
+
Running system must have following executables present:
|
24
|
+
- scanelf (from pax-utils)
|
25
|
+
|
26
|
+
Additionally, for musl executables and libraries, following are necessary:
|
27
|
+
- ldd
|
28
|
+
|
29
|
+
Additionally, for glibc executables and libraries, following are necessary:
|
30
|
+
- llvm-readelf
|
31
|
+
|
23
32
|
## Usage
|
24
33
|
|
25
34
|
For now this is under ongoing development, though semantic versioning will apply.
|
data/lib/bwrap/args/bind.rb
CHANGED
@@ -53,10 +53,6 @@ class Bwrap::Args::Bind
|
|
53
53
|
#
|
54
54
|
# Or maybe the data should be calculated and these are excluded in
|
55
55
|
# Construct#bwrap_arguments?
|
56
|
-
#
|
57
|
-
# NOTE: After making Config optional, now this requires config to be preset
|
58
|
-
# for full_system_mounts option to have any effect. Maybe it should always
|
59
|
-
# be like so by default...?
|
60
56
|
return if @config && !@config&.full_system_mounts
|
61
57
|
|
62
58
|
@library_bind.handle_given_command
|
data/lib/bwrap/args/construct.rb
CHANGED
@@ -10,6 +10,7 @@ require_relative "environment"
|
|
10
10
|
require_relative "features"
|
11
11
|
require_relative "machine_id"
|
12
12
|
require_relative "mount"
|
13
|
+
require_relative "namespace"
|
13
14
|
require_relative "network"
|
14
15
|
require_relative "user"
|
15
16
|
|
@@ -63,7 +64,7 @@ class Bwrap::Args::Construct
|
|
63
64
|
proc_mount
|
64
65
|
tmp_as_tmpfs
|
65
66
|
@bind.bind_home_directory
|
66
|
-
@
|
67
|
+
@namespace.shares
|
67
68
|
@network.share_net
|
68
69
|
@network.hostname
|
69
70
|
@args.add :environment, @environment.environment_variables
|
@@ -145,6 +146,9 @@ class Bwrap::Args::Construct
|
|
145
146
|
@machine_id = Bwrap::Args::MachineId.new
|
146
147
|
@machine_id.config = @config
|
147
148
|
|
149
|
+
@namespace = Bwrap::Args::Namespace.new @args
|
150
|
+
@namespace.config = @config
|
151
|
+
|
148
152
|
@network = Bwrap::Args::Network.new @args
|
149
153
|
@network.config = @config
|
150
154
|
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bwrap/output"
|
4
|
+
require_relative "args"
|
5
|
+
|
6
|
+
# Namespace related arguments.
|
7
|
+
#
|
8
|
+
# Mostly for handling --unshare-*
|
9
|
+
class Bwrap::Args::Namespace
|
10
|
+
include Bwrap::Output
|
11
|
+
|
12
|
+
# Instance of {Config}.
|
13
|
+
attr_writer :config
|
14
|
+
|
15
|
+
# @param args [Bwrap::Args::Args] Arguments to be passed to bwrap.
|
16
|
+
def initialize args
|
17
|
+
@args = args
|
18
|
+
end
|
19
|
+
|
20
|
+
def shares
|
21
|
+
return unless @config&.unshare_all
|
22
|
+
|
23
|
+
@args.add :unshare_all, "--unshare-all" # Practically means that there would be nothing in the sandbox by default.
|
24
|
+
end
|
25
|
+
end
|
data/lib/bwrap/args/network.rb
CHANGED
@@ -24,7 +24,12 @@ class Bwrap::Args::Network
|
|
24
24
|
end
|
25
25
|
|
26
26
|
# Arguments to read-only bind /etc/resolv.conf.
|
27
|
+
#
|
28
|
+
# TODO: Probably it should be checked if target will have the symlink present before
|
29
|
+
# doing this automatically. For that reason, now this will need a flag.
|
27
30
|
def resolv_conf
|
31
|
+
return unless @config&.resolv_conf
|
32
|
+
|
28
33
|
# We can’t really bind symlinks, so let’s resolve real path to resolv.conf, in case it is symlinked.
|
29
34
|
source_resolv_conf = Pathname.new "/etc/resolv.conf"
|
30
35
|
source_resolv_conf = source_resolv_conf.realpath
|
data/lib/bwrap/bwrap.rb
CHANGED
@@ -98,9 +98,11 @@ class Bwrap::Bwrap
|
|
98
98
|
kwargs[:log_callback] ||= 1
|
99
99
|
kwargs[:log_callback] += 1
|
100
100
|
|
101
|
-
execute exec_command, **kwargs
|
101
|
+
result = execute exec_command, **kwargs
|
102
102
|
|
103
103
|
@construct.cleanup
|
104
|
+
|
105
|
+
result
|
104
106
|
end
|
105
107
|
|
106
108
|
# Convenience method to executes a command that is inside bwrap.
|
data/lib/bwrap/config.rb
CHANGED
@@ -53,8 +53,6 @@ class Bwrap::Config
|
|
53
53
|
# @return [#each] Array of executables to bind
|
54
54
|
attr_accessor :extra_executables
|
55
55
|
|
56
|
-
# TODO: IIRC this doesn’t match the reality any more. So write correct documentation.
|
57
|
-
#
|
58
56
|
# Causes libraries required by the executable given to {Bwrap#run} to be
|
59
57
|
# mounted inside sandbox.
|
60
58
|
#
|
@@ -62,6 +60,10 @@ class Bwrap::Config
|
|
62
60
|
# using {#libdir_mounts=}
|
63
61
|
#
|
64
62
|
# @return [Boolean] true if Linux library loaders are mounted inside chroot
|
63
|
+
#
|
64
|
+
# TODO: Since this only causes given executable be scanned for dependencies,
|
65
|
+
# and not ”--bind / /”, this one should be deprecated and something like
|
66
|
+
# ”@config.bind_dependents = true” should be added as alias of this.
|
65
67
|
attr_accessor :full_system_mounts
|
66
68
|
|
67
69
|
# If set to `true`, things like /dev/dri is bound to sandbox to enable usage
|
@@ -98,9 +100,22 @@ class Bwrap::Config
|
|
98
100
|
# Given file as bound as /etc/machine_id.
|
99
101
|
attr_accessor :machine_id
|
100
102
|
|
103
|
+
# If set to truthy, /etc/resolv.conf will be bound to target.
|
104
|
+
attr_accessor :resolv_conf
|
105
|
+
|
101
106
|
# @return [Boolean] true if network should be shared from host.
|
102
107
|
attr_accessor :share_net
|
103
108
|
|
109
|
+
# Set to truthy to remove (see bwrap’s --unshare-all) all namespaces from
|
110
|
+
# target chroot.
|
111
|
+
#
|
112
|
+
# Defaults to true.
|
113
|
+
#
|
114
|
+
# TODO: Create more fine grained control for sharing logic than this one.
|
115
|
+
#
|
116
|
+
# @return [Boolean] true if all namespaces are tried to be removed from target.
|
117
|
+
attr_accessor :unshare_all
|
118
|
+
|
104
119
|
# Name of the user inside chroot.
|
105
120
|
#
|
106
121
|
# This is optional and defaults to no user.
|
@@ -166,6 +181,7 @@ class Bwrap::Config
|
|
166
181
|
@env_paths = []
|
167
182
|
@ro_binds = {}
|
168
183
|
@tmpdir = Dir.tmpdir
|
184
|
+
@unshare_all = true
|
169
185
|
end
|
170
186
|
|
171
187
|
def binaries_from= array
|
@@ -0,0 +1 @@
|
|
1
|
+
# frozen_string_literal: true
|
data/lib/bwrap/execution.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bwrap/execution"
|
4
|
+
require "bwrap/output"
|
5
|
+
require_relative "../library"
|
6
|
+
|
7
|
+
# Base definitions for library resolver subclasses.
|
8
|
+
class Bwrap::Resolvers::Library::Base
|
9
|
+
include Bwrap::Execution
|
10
|
+
include Bwrap::Output
|
11
|
+
|
12
|
+
private def convert_binary_paths binary_paths
|
13
|
+
case binary_paths
|
14
|
+
when String
|
15
|
+
[ binary_paths ]
|
16
|
+
when Pathname
|
17
|
+
[ binary_paths.to_s ]
|
18
|
+
else
|
19
|
+
binary_paths
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bwrap/execution"
|
4
|
+
require "bwrap/output"
|
5
|
+
require_relative "llvm_readelf"
|
6
|
+
require_relative "musl"
|
7
|
+
require_relative "../resolvers"
|
8
|
+
|
9
|
+
# See ../library.rb for class documentation.
|
10
|
+
class Bwrap::Resolvers::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
|
+
# Empties `@@needed_libraries_cache`.
|
18
|
+
def self.clear_needed_libraries_cache
|
19
|
+
@@needed_libraries_cache.clear
|
20
|
+
end
|
21
|
+
|
22
|
+
class << self
|
23
|
+
def needed_libraries_cache
|
24
|
+
@@needed_libraries_cache
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Otherwise similar to {#needed_libraries}, but checks used libc to handle musl executables.
|
29
|
+
#
|
30
|
+
# @param executable [String] Path to the executable to find dependencies for
|
31
|
+
# @return [Array] Libraries the executable needs, if any
|
32
|
+
def libraries_needed_by executable
|
33
|
+
trace "Finding libraries needed by #{executable}"
|
34
|
+
|
35
|
+
# %i == interpreter, the library used to load the executable by kernel.
|
36
|
+
# %F == Path to given file.
|
37
|
+
output_format = "%i::SEPARATOR::%F"
|
38
|
+
scanelf_command = %W{ scanelf --nobanner --quiet --format #{output_format} }
|
39
|
+
scanelf_command << executable
|
40
|
+
|
41
|
+
data = execvalue scanelf_command
|
42
|
+
|
43
|
+
# If data is empty, target probably is a script of some sort.
|
44
|
+
if data.empty?
|
45
|
+
return []
|
46
|
+
end
|
47
|
+
|
48
|
+
data = data.strip
|
49
|
+
interpreter, _executable_path = data.split "::SEPARATOR::"
|
50
|
+
interpreter = Pathname.new interpreter
|
51
|
+
|
52
|
+
if interpreter.basename.to_s[0..6] == "ld-musl"
|
53
|
+
trace "Resolved to musl interpreter: #{interpreter}"
|
54
|
+
musl_needed_libraries executable
|
55
|
+
else
|
56
|
+
trace "Defaulting to glibc interpreter: #{interpreter}"
|
57
|
+
# For glibc, scanelf can return full paths for us most of time.
|
58
|
+
needed_libraries executable
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# @param binary_paths [String, Array] one or more paths to be resolved
|
63
|
+
def musl_needed_libraries binary_paths
|
64
|
+
musl = Musl.new
|
65
|
+
@needed_libraries = musl.needed_libraries binary_paths
|
66
|
+
end
|
67
|
+
|
68
|
+
# @param binary_paths [String, Array] one or more paths to be resolved
|
69
|
+
def needed_libraries binary_paths
|
70
|
+
llvm_readelf = LLVMReadelf.new
|
71
|
+
@needed_libraries = llvm_readelf.needed_libraries binary_paths
|
72
|
+
end
|
73
|
+
end
|
74
|
+
# class Library ended
|
@@ -0,0 +1,133 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
# Used via {Bwrap::Resolvers::Library}.
|
6
|
+
#
|
7
|
+
# @api private
|
8
|
+
class Bwrap::Resolvers::Library::LLVMReadelf < Bwrap::Resolvers::Library::Base
|
9
|
+
# Resolve dependents using llvm-readelf.
|
10
|
+
#
|
11
|
+
# @param binary_paths [String, Array] one or more paths to be resolved
|
12
|
+
def needed_libraries binary_paths
|
13
|
+
raise ArgumentError, "binary_paths is nil, expected an Array" if binary_paths.nil?
|
14
|
+
|
15
|
+
trace "Finding libraries #{binary_paths} requires"
|
16
|
+
@needed_libraries = []
|
17
|
+
|
18
|
+
llvm_readelf_command = %w{ llvm-readelf --needed-libs }
|
19
|
+
|
20
|
+
binary_paths = convert_binary_paths binary_paths
|
21
|
+
|
22
|
+
# Check if the exe is already resolved.
|
23
|
+
binary_paths.delete_if do |binary_path|
|
24
|
+
Bwrap::Resolvers::Library.needed_libraries_cache.include? binary_path
|
25
|
+
end
|
26
|
+
|
27
|
+
return [] if binary_paths.empty?
|
28
|
+
|
29
|
+
data = execvalue(llvm_readelf_command + binary_paths)
|
30
|
+
parse_llvm_readelf_output binary_paths, data
|
31
|
+
|
32
|
+
@needed_libraries
|
33
|
+
end
|
34
|
+
|
35
|
+
# Parses output returned by llvm-readelf --needed-libraries
|
36
|
+
#
|
37
|
+
# Sets libraries to @needed_libraries variable.
|
38
|
+
private def parse_llvm_readelf_output binary_paths, data
|
39
|
+
iter = data.split("\n").each
|
40
|
+
source_binary = binary_paths.first
|
41
|
+
begin
|
42
|
+
while (line = iter.next)
|
43
|
+
source_binary = line[6..-1].strip if line[0..5] == "File: "
|
44
|
+
next unless line[0..16] == "NeededLibraries ["
|
45
|
+
|
46
|
+
while (library = iter.next)
|
47
|
+
library = library.strip
|
48
|
+
# End of library list for current NeededLibraries block.
|
49
|
+
break if library == "]"
|
50
|
+
|
51
|
+
library = convert_to_full_path source_binary, library
|
52
|
+
|
53
|
+
add_library_to_needed_libraries library
|
54
|
+
end
|
55
|
+
end
|
56
|
+
rescue StopIteration
|
57
|
+
# End of the iteration.
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# NOTE: Maybe this could be in general file here, if needed elsewhere also?
|
62
|
+
# This also applies to some other methods here.
|
63
|
+
#
|
64
|
+
# Finds where given library would be loaded from.
|
65
|
+
#
|
66
|
+
# source_binary is used to to if it has RPATH set as third possibility.
|
67
|
+
# TODO: Implement above.
|
68
|
+
#
|
69
|
+
# @param source_binary [String] Executable or library which is loading the binary
|
70
|
+
private def convert_to_full_path source_binary, library
|
71
|
+
# TODO: Somewhere put a cleanup for this variable, so this is erased
|
72
|
+
# before application is run. That will save at least 200 kB of memory.
|
73
|
+
@@ld_so_cache ||= File.read("/etc/ld.so.cache", mode: "rb")
|
74
|
+
|
75
|
+
path_regex = %r{[\w\-/. ]{3,}}
|
76
|
+
|
77
|
+
check_next = false
|
78
|
+
@@ld_so_cache.scan(path_regex).each do |match|
|
79
|
+
if check_next
|
80
|
+
# TODO: Any sense checking for executable bit?
|
81
|
+
return match if File.exist? match
|
82
|
+
|
83
|
+
check_next = false
|
84
|
+
end
|
85
|
+
|
86
|
+
check_next = true if match == library
|
87
|
+
end
|
88
|
+
|
89
|
+
warn "Failed to resolve full path of library #{library}, needed by #{source_binary}."
|
90
|
+
library
|
91
|
+
end
|
92
|
+
|
93
|
+
# @param library [Array] library to add.
|
94
|
+
private def add_library_to_needed_libraries library
|
95
|
+
raise ArgumentError, "library is nil, expected a String" if library.nil?
|
96
|
+
|
97
|
+
return if @needed_libraries.include? library
|
98
|
+
|
99
|
+
# Probably no sense to log these unless tracing,
|
100
|
+
# as dependencies should work most of time.
|
101
|
+
#
|
102
|
+
# It also outputs tons of output for more complex programs.
|
103
|
+
trace "Binding #{library}"
|
104
|
+
|
105
|
+
@needed_libraries << library
|
106
|
+
|
107
|
+
# Also check if requisite libraries needs some libraries.
|
108
|
+
inner = Bwrap::Resolvers::Library.new
|
109
|
+
@needed_libraries |= inner.needed_libraries library
|
110
|
+
|
111
|
+
Bwrap::Resolvers::Library.needed_libraries_cache << library
|
112
|
+
end
|
113
|
+
|
114
|
+
# @param libraries [Array] libraries to add.
|
115
|
+
private def add_libraries_to_needed_libraries libraries
|
116
|
+
# Add to needed libraries if not already added.
|
117
|
+
(@needed_libraries & libraries).each do |library|
|
118
|
+
# Probably no sense to log these unless tracing,
|
119
|
+
# as dependencies should work most of time.
|
120
|
+
#
|
121
|
+
# It also outputs tons of output for more complex programs.
|
122
|
+
trace "Binding #{library}"
|
123
|
+
end
|
124
|
+
|
125
|
+
@needed_libraries |= libraries
|
126
|
+
|
127
|
+
# Also check if requisite libraries needs some libraries.
|
128
|
+
inner = Bwrap::Resolvers::Library.new
|
129
|
+
@needed_libraries |= inner.needed_libraries libraries
|
130
|
+
|
131
|
+
Bwrap::Resolvers::Library.needed_libraries_cache |= libraries
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
# Used via {Bwrap::Resolvers::Library}.
|
6
|
+
#
|
7
|
+
# @api private
|
8
|
+
class Bwrap::Resolvers::Library::Musl < Bwrap::Resolvers::Library::Base
|
9
|
+
# @param binary_paths [String, Array] one or more paths to be resolved
|
10
|
+
def needed_libraries binary_paths
|
11
|
+
trace "Finding musl libraries #{binary_paths} requires"
|
12
|
+
@needed_libraries = []
|
13
|
+
|
14
|
+
binary_paths = convert_binary_paths binary_paths
|
15
|
+
|
16
|
+
# Check if the exe is already resolved.
|
17
|
+
binary_paths.delete_if do |binary_path|
|
18
|
+
Bwrap::Resolvers::Library.needed_libraries_cache.include? binary_path
|
19
|
+
end
|
20
|
+
|
21
|
+
return [] if binary_paths.empty?
|
22
|
+
|
23
|
+
binary_paths.each do |binary_path|
|
24
|
+
output = execvalue %W{ ldd #{binary_path} }
|
25
|
+
lines = output.split "\n"
|
26
|
+
_interpreter_line = lines.shift
|
27
|
+
|
28
|
+
lines.each do |line|
|
29
|
+
parse_ldd_line line
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
@needed_libraries
|
34
|
+
end
|
35
|
+
|
36
|
+
# Used by {#musl_needed_libraries}.
|
37
|
+
private def parse_ldd_line line
|
38
|
+
line = line.strip
|
39
|
+
_library_name, library_data = line.split " => "
|
40
|
+
|
41
|
+
matches = library_data.match(/(.*) \(0x[0-9a-f]+\)/)
|
42
|
+
library_path = matches[1]
|
43
|
+
|
44
|
+
unless @needed_libraries.include? library_path
|
45
|
+
@needed_libraries << library_path
|
46
|
+
end
|
47
|
+
|
48
|
+
# Also check if requisite libraries needs some libraries.
|
49
|
+
inner = Bwrap::Resolvers::Library.new
|
50
|
+
@needed_libraries |= inner.musl_needed_libraries library_path
|
51
|
+
|
52
|
+
Bwrap::Resolvers::Library.needed_libraries_cache << library_path
|
53
|
+
end
|
54
|
+
end
|
@@ -1,160 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "bwrap/execution"
|
4
|
-
require "bwrap/output"
|
5
3
|
require_relative "resolvers"
|
6
4
|
|
7
5
|
# Class to clean up namespace for implementation specific reasons.
|
8
6
|
#
|
9
7
|
# @api private
|
10
8
|
class Bwrap::Resolvers::Library
|
11
|
-
|
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
|
-
# Empties `@@needed_libraries_cache`.
|
18
|
-
def self.clear_needed_libraries_cache
|
19
|
-
@@needed_libraries_cache.clear
|
20
|
-
end
|
21
|
-
|
22
|
-
# Otherwise similar to {#needed_libraries}, but checks used libc to handle musl executables.
|
23
|
-
#
|
24
|
-
# @param executable [String] Path to the executable to find dependencies for
|
25
|
-
# @return [Array] Libraries the executable needs, if any
|
26
|
-
def libraries_needed_by executable
|
27
|
-
# %i == interpreter, the library used to load the executable by kernel.
|
28
|
-
# %F == Path to given file.
|
29
|
-
output_format = "%i::SEPARATOR::%F"
|
30
|
-
scanelf_command = %W{ scanelf --nobanner --quiet --format #{output_format} }
|
31
|
-
scanelf_command << executable
|
32
|
-
|
33
|
-
data = execvalue scanelf_command
|
34
|
-
|
35
|
-
# If data is empty, target probably is a script of some sort.
|
36
|
-
if data.empty?
|
37
|
-
return []
|
38
|
-
end
|
39
|
-
|
40
|
-
data = data.strip
|
41
|
-
interpreter, _executable_path = data.split "::SEPARATOR::"
|
42
|
-
interpreter = Pathname.new interpreter
|
43
|
-
|
44
|
-
if interpreter.basename.to_s[0..6] == "ld-musl"
|
45
|
-
musl_needed_libraries executable
|
46
|
-
else
|
47
|
-
# For glibc, scanelf can return full paths for us most of time.
|
48
|
-
needed_libraries executable
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
# @param binary_paths [String, Array] one or more paths to be resolved
|
53
|
-
def musl_needed_libraries binary_paths
|
54
|
-
trace "Finding musl libraries #{binary_paths} requires"
|
55
|
-
@needed_libraries = []
|
56
|
-
|
57
|
-
binary_paths = convert_binary_paths binary_paths
|
58
|
-
|
59
|
-
# Check if the exe is already resolved.
|
60
|
-
binary_paths.delete_if do |binary_path|
|
61
|
-
@@needed_libraries_cache.include? binary_path
|
62
|
-
end
|
63
|
-
|
64
|
-
return [] if binary_paths.empty?
|
65
|
-
|
66
|
-
binary_paths.each do |binary_path|
|
67
|
-
output = execvalue %W{ ldd #{binary_path} }
|
68
|
-
lines = output.split "\n"
|
69
|
-
_interpreter_line = lines.shift
|
70
|
-
|
71
|
-
lines.each do |line|
|
72
|
-
parse_ldd_line line
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
@needed_libraries
|
77
|
-
end
|
78
|
-
|
79
|
-
# @param binary_paths [String, Array] one or more paths to be resolved
|
80
|
-
def needed_libraries binary_paths
|
81
|
-
trace "Finding libraries #{binary_paths} requires"
|
82
|
-
@needed_libraries = []
|
83
|
-
|
84
|
-
# %i == interpreter, the library used to load the executable by kernel.
|
85
|
-
output_format = "%F::SEPARATOR::%n"
|
86
|
-
scanelf_command = %W{ scanelf --nobanner --quiet --format #{output_format} --ldcache --needed }
|
87
|
-
|
88
|
-
binary_paths = convert_binary_paths binary_paths
|
89
|
-
|
90
|
-
# Check if the exe is already resolved.
|
91
|
-
binary_paths.delete_if do |binary_path|
|
92
|
-
@@needed_libraries_cache.include? binary_path
|
93
|
-
end
|
94
|
-
|
95
|
-
return [] if binary_paths.empty?
|
96
|
-
|
97
|
-
data = execvalue(scanelf_command + binary_paths)
|
98
|
-
trace "scanelf found following libraries: #{data}"
|
99
|
-
|
100
|
-
lines = data.split "\n"
|
101
|
-
lines.each do |line|
|
102
|
-
parse_scanelf_line line
|
103
|
-
end
|
104
|
-
|
105
|
-
@needed_libraries
|
106
|
-
end
|
107
|
-
|
108
|
-
private def convert_binary_paths binary_paths
|
109
|
-
if binary_paths.is_a? String
|
110
|
-
[ binary_paths ]
|
111
|
-
elsif binary_paths.is_a? Pathname
|
112
|
-
[ binary_paths.to_s ]
|
113
|
-
else
|
114
|
-
binary_paths
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
# Used by {#needed_libraries}.
|
119
|
-
private def parse_scanelf_line line
|
120
|
-
binary_path, libraries_line = line.split "::SEPARATOR::"
|
121
|
-
libraries = libraries_line.split ","
|
122
|
-
|
123
|
-
# Add to needed libraries if not already added.
|
124
|
-
(@needed_libraries & libraries).each do |library|
|
125
|
-
# Probably no sense to log these unless tracing,
|
126
|
-
# as dependencies should work most of time.
|
127
|
-
#
|
128
|
-
# It also outputs tons of output for more complex programs.
|
129
|
-
trace "Binding #{library} as dependency of #{binary_path}"
|
130
|
-
end
|
131
|
-
|
132
|
-
@needed_libraries |= libraries
|
133
|
-
|
134
|
-
# Also check if requisite libraries needs some libraries.
|
135
|
-
inner = Bwrap::Resolvers::Library.new
|
136
|
-
@needed_libraries |= inner.needed_libraries libraries
|
137
|
-
|
138
|
-
@@needed_libraries_cache |= libraries
|
139
|
-
end
|
140
|
-
|
141
|
-
# Used by {#musl_needed_libraries}.
|
142
|
-
private def parse_ldd_line line
|
143
|
-
line = line.strip
|
144
|
-
_library_name, library_data = line.split " => "
|
145
|
-
|
146
|
-
matches = library_data.match(/(.*) \(0x[0-9a-f]+\)/)
|
147
|
-
library_path = matches[1]
|
148
|
-
|
149
|
-
unless @needed_libraries.include? library_path
|
150
|
-
@needed_libraries << library_path
|
151
|
-
end
|
152
|
-
|
153
|
-
# Also check if requisite libraries needs some libraries.
|
154
|
-
inner = Bwrap::Resolvers::Library.new
|
155
|
-
@needed_libraries |= inner.musl_needed_libraries library_path
|
156
|
-
|
157
|
-
@@needed_libraries_cache << library_path
|
158
|
-
end
|
9
|
+
# Declared here only for convenience.
|
159
10
|
end
|
160
|
-
|
11
|
+
|
12
|
+
require_relative "library/library"
|
data/lib/bwrap/version.rb
CHANGED
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.
|
4
|
+
version: 1.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samu Voutilainen
|
@@ -10,8 +10,8 @@ bindir: bin
|
|
10
10
|
cert_chain:
|
11
11
|
- |
|
12
12
|
-----BEGIN CERTIFICATE-----
|
13
|
-
|
14
|
-
|
13
|
+
MIID8DCCAligAwIBAgIBAjANBgkqhkiG9w0BAQsFADAeMRwwGgYDVQQDDBNid3Jh
|
14
|
+
cC9EQz1zbWFyL0RDPWZpMB4XDTIzMDEwNjA2NTUyNFoXDTI0MDEwNjA2NTUyNFow
|
15
15
|
HjEcMBoGA1UEAwwTYndyYXAvREM9c21hci9EQz1maTCCAaIwDQYJKoZIhvcNAQEB
|
16
16
|
BQADggGPADCCAYoCggGBAKUQ5wFdLLIejwiCNeGMlbApquoC0jT59H+d6zOLWxYd
|
17
17
|
RRdum9G1lxFFFolEsFj5RSplg/SlhAhYRMUjDHiSk/usxVcOt28h4sdiFTbi1zKA
|
@@ -21,20 +21,19 @@ cert_chain:
|
|
21
21
|
NqpsI0mQejnq+QdiNz9gAWObO+UhrOv5S7E0NYQTaf1e3G56kCmIG9p0pFXjWNPx
|
22
22
|
DhL6YDoizVSQKTllYWbDhBx0+D+sevtmKAy0vHDAY33teAQYOxgeE/iXqvvROPU7
|
23
23
|
HNOAqNazQHwPsTepLT9Dc/5bVbazL1MNNiWh5ZYjmJnlGSttHhM/xsZZkckJ20oh
|
24
|
-
|
25
|
-
sDAdBgNVHQ4EFgQUywyVCkA/
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
MRxVMHiVAqY=
|
24
|
+
0iJSyUprpR2epHP8832n6wIDAQABozkwNzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE
|
25
|
+
sDAdBgNVHQ4EFgQUywyVCkA/Pr5zdaaMvAVlHKSXeJkwDQYJKoZIhvcNAQELBQAD
|
26
|
+
ggGBAGmSe4zkcmNd3JfmTA9CDpBu3j6qiPnbk2x8vTjDQAyAGRjX8Depzz39jUbF
|
27
|
+
cmmL/J5XqqkZaYy7X+w2nWVYk8BwmAP3ft6L6qO0rmZhOtfsyTzf0fI1zY20Y98W
|
28
|
+
uoDoS2cL6fIJ8Gv6B4tXCSZO1cQOHMAhzAeRGbfn0InbDtalfVbYFmnmo9PqJz4C
|
29
|
+
kRUFHNCTRt+YAneAZ2gAU4r89EuNheyyEmPonWHjCwPIGKS/rsChFWIU22wrZkGd
|
30
|
+
aWT3as+jC2gDiQTw82JalFWsqK9p9UxsRt1lkV4mb5NSDcKl7ApI1TAW2EANeLOx
|
31
|
+
PWJbiDgQIrErC5lDu25gzWF+g5sYc7uaMcKxS8BqAggMWuW/lUcNX8e+4WdDAPgO
|
32
|
+
tDIK8ZQo4kVJE9EQTA4LsP4TMNDn18vBr0aIY92p+uq31rocusojfAszU50DSw3M
|
33
|
+
7a31nUjVeQjpooaUQi6ECFr+Neidh3jhzreVfXqjxMkPOYLlCAmd9E1izCTRIgLS
|
34
|
+
cAzqsw==
|
36
35
|
-----END CERTIFICATE-----
|
37
|
-
date:
|
36
|
+
date: 2023-01-06 00:00:00.000000000 Z
|
38
37
|
dependencies:
|
39
38
|
- !ruby/object:Gem::Dependency
|
40
39
|
name: bundler
|
@@ -158,6 +157,7 @@ files:
|
|
158
157
|
- lib/bwrap/args/features/ruby_binds.rb
|
159
158
|
- lib/bwrap/args/machine_id.rb
|
160
159
|
- lib/bwrap/args/mount.rb
|
160
|
+
- lib/bwrap/args/namespace.rb
|
161
161
|
- lib/bwrap/args/network.rb
|
162
162
|
- lib/bwrap/args/user.rb
|
163
163
|
- lib/bwrap/bwrap.rb
|
@@ -166,6 +166,7 @@ files:
|
|
166
166
|
- lib/bwrap/config/features.rb
|
167
167
|
- lib/bwrap/config/features/base.rb
|
168
168
|
- lib/bwrap/config/features/ruby.rb
|
169
|
+
- lib/bwrap/exceptions.rb
|
169
170
|
- lib/bwrap/execution.rb
|
170
171
|
- lib/bwrap/execution/exceptions.rb
|
171
172
|
- lib/bwrap/execution/exec.rb
|
@@ -182,6 +183,10 @@ files:
|
|
182
183
|
- lib/bwrap/output/output_impl.rb
|
183
184
|
- lib/bwrap/resolvers/executable.rb
|
184
185
|
- lib/bwrap/resolvers/library.rb
|
186
|
+
- lib/bwrap/resolvers/library/base.rb
|
187
|
+
- lib/bwrap/resolvers/library/library.rb
|
188
|
+
- lib/bwrap/resolvers/library/llvm_readelf.rb
|
189
|
+
- lib/bwrap/resolvers/library/musl.rb
|
185
190
|
- lib/bwrap/resolvers/mime.rb
|
186
191
|
- lib/bwrap/resolvers/resolvers.rb
|
187
192
|
- lib/bwrap/version.rb
|
metadata.gz.sig
CHANGED
Binary file
|