mxc 0.3.0-x86_64-linux → 0.4.1-x86_64-linux
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
- data/README.md +2 -0
- data/lib/mxc/3.2/mxc.so +0 -0
- data/lib/mxc/3.3/mxc.so +0 -0
- data/lib/mxc/3.4/mxc.so +0 -0
- data/lib/mxc/4.0/mxc.so +0 -0
- data/lib/mxc/libraries.rb +138 -0
- data/lib/mxc/load_commands.rb +50 -0
- data/lib/mxc/sandbox.rb +75 -13
- data/lib/mxc/version.rb +1 -1
- data/lib/mxc.rb +2 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e823dba4eda34547c8d9f69f757159853a4a7dcfbe4c812977d017aeffab9bad
|
|
4
|
+
data.tar.gz: '0249efbddc710c8633c134eb7ae6efb82f91855a52c7e55b5f784282d49e15a8'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7f070db2714abec61e97ac6f88787c0a07f5bb2add5bd6596dcbe6e44a7b77502f849fdaeb9dab2ec253069a3b5877b3e48e73df6935ef61b6369c923f64a355
|
|
7
|
+
data.tar.gz: 622128cab7fced35b66d24348b5d8036b7e175859c984e1147662f2fd42d8293c390a9e683ff2faee5acefd5d4f1e0efc954e1622db7744786d20525c223adf4
|
data/README.md
CHANGED
|
@@ -128,6 +128,8 @@ MXC.backends # => [#<MXC::Backend name=:bubblewrap ...>]
|
|
|
128
128
|
|
|
129
129
|
On Windows, a single String runs through `cmd.exe` instead of `sh`. See [Running Commands](https://crmne.github.io/mxc/running-commands/#windows) and [Policies](https://crmne.github.io/mxc/policies/#windows) for what else differs.
|
|
130
130
|
|
|
131
|
+
A sandbox controls files, network, and resources. It does not always hide other processes: on some backends a command can read their command lines, and on macOS the environment your application started with. [Policies](https://crmne.github.io/mxc/policies/#what-the-command-can-see-of-other-processes) lists what each backend shows.
|
|
132
|
+
|
|
131
133
|
Docker blocks the namespaces Bubblewrap needs by default, so a default container runs sandboxes on Landlock. [Running in Docker](https://crmne.github.io/mxc/running-in-docker/) shows what that gives up, and the smallest set of changes that makes Bubblewrap work, with a seccomp profile and a Kamal configuration for a job role.
|
|
132
134
|
|
|
133
135
|
## Documentation
|
data/lib/mxc/3.2/mxc.so
CHANGED
|
Binary file
|
data/lib/mxc/3.3/mxc.so
CHANGED
|
Binary file
|
data/lib/mxc/3.4/mxc.so
CHANGED
|
Binary file
|
data/lib/mxc/4.0/mxc.so
CHANGED
|
Binary file
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'open3'
|
|
4
|
+
require 'shellwords'
|
|
5
|
+
|
|
6
|
+
module MXC
|
|
7
|
+
# Finds the shared library files programs load, directly or through
|
|
8
|
+
# other libraries, so a sandbox can read them and nothing beside them. Only macOS needs this: Seatbelt
|
|
9
|
+
# sandboxes read the system's libraries but not those a package manager
|
|
10
|
+
# installs, such as Homebrew's, which a program like Ruby may link. The
|
|
11
|
+
# libraries come from the programs' load commands, read with otool from
|
|
12
|
+
# the Command Line Tools. Without them nothing is found, because
|
|
13
|
+
# /usr/bin/otool would offer to install them instead.
|
|
14
|
+
module Libraries # :nodoc:
|
|
15
|
+
OTOOL = '/usr/bin/otool'
|
|
16
|
+
XCODE_SELECT = '/usr/bin/xcode-select'
|
|
17
|
+
SYSTEM = %w[/usr/lib/ /System/ /Library/].freeze
|
|
18
|
+
TOKEN = %r{\A@(loader_path|executable_path|rpath)/}
|
|
19
|
+
|
|
20
|
+
@links = {}
|
|
21
|
+
@lock = Mutex.new
|
|
22
|
+
|
|
23
|
+
class << self
|
|
24
|
+
# Returns the real paths of the library files +binaries+ load outside
|
|
25
|
+
# the system's own, empty where none are needed or otool is missing.
|
|
26
|
+
# +executable+ is the program that loads them, for libraries named
|
|
27
|
+
# relative to it.
|
|
28
|
+
def files(binaries, executable: nil)
|
|
29
|
+
return [] if binaries.empty? || !available?
|
|
30
|
+
|
|
31
|
+
libraries(binaries, executable)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Returns the path of the program +arguments+ start: the first argument, or the first
|
|
35
|
+
# word of a command for the shell, found on +path+ or under +directory+. Returns nil
|
|
36
|
+
# when there is none.
|
|
37
|
+
def program(arguments, path:, directory:)
|
|
38
|
+
name = program_name(arguments)
|
|
39
|
+
return if name.nil?
|
|
40
|
+
return File.expand_path(name, directory || '/') if name.include?('/')
|
|
41
|
+
|
|
42
|
+
path.to_s.split(File::PATH_SEPARATOR).map { |entry| File.join(entry, name) }
|
|
43
|
+
.find { |candidate| File.file?(candidate) && File.executable?(candidate) }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Returns true when this host can list a program's libraries.
|
|
47
|
+
def available?
|
|
48
|
+
return @available if defined?(@available)
|
|
49
|
+
|
|
50
|
+
@available = RUBY_PLATFORM.include?('darwin') && File.executable?(OTOOL) && developer_tools?
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def program_name(arguments)
|
|
56
|
+
arguments.one? ? Shellwords.split(arguments.first).first : arguments.first
|
|
57
|
+
rescue ArgumentError
|
|
58
|
+
nil
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def libraries(binaries, executable)
|
|
62
|
+
roots = binaries.filter_map { |binary| real_path(binary) }
|
|
63
|
+
links_of(roots)
|
|
64
|
+
found = {}
|
|
65
|
+
roots.each { |root| visit(root, executable || root, [], found) }
|
|
66
|
+
found.keys
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def visit(path, executable, inherited, found)
|
|
70
|
+
dependencies(path, links_of([path]).fetch(path), executable, inherited).each do |library, rpaths|
|
|
71
|
+
next if found.key?(library)
|
|
72
|
+
|
|
73
|
+
found[library] = true
|
|
74
|
+
visit(library, executable, rpaths, found)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def developer_tools?
|
|
79
|
+
system(XCODE_SELECT, '-p', out: File::NULL, err: File::NULL) == true
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def dependencies(path, links, executable, inherited)
|
|
83
|
+
rpaths = links[:rpaths].filter_map { |rpath| expand(rpath, path, executable) } + inherited
|
|
84
|
+
links[:libraries].filter_map do |name|
|
|
85
|
+
next if system?(name)
|
|
86
|
+
|
|
87
|
+
library = locate(name, path, executable, rpaths)
|
|
88
|
+
[library, rpaths] if library && !system?(library)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def locate(name, loader, executable, rpaths)
|
|
93
|
+
relative = name.delete_prefix('@rpath/')
|
|
94
|
+
candidates = if relative == name
|
|
95
|
+
[expand(name, loader, executable)]
|
|
96
|
+
else
|
|
97
|
+
rpaths.map { |rpath| File.join(rpath, relative) }
|
|
98
|
+
end
|
|
99
|
+
candidates.compact.lazy.filter_map { |candidate| real_path(candidate) }.first
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def expand(name, loader, executable)
|
|
103
|
+
token = name[TOKEN, 1]
|
|
104
|
+
return name unless token
|
|
105
|
+
return if token == 'rpath'
|
|
106
|
+
|
|
107
|
+
base = token == 'loader_path' ? loader : executable
|
|
108
|
+
File.expand_path(name.sub(TOKEN, ''), File.dirname(base))
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def system?(path)
|
|
112
|
+
path.start_with?(*SYSTEM)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def real_path(path)
|
|
116
|
+
path = File.realpath(path)
|
|
117
|
+
path if File.file?(path)
|
|
118
|
+
rescue SystemCallError
|
|
119
|
+
nil
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def links_of(paths)
|
|
123
|
+
@lock.synchronize do
|
|
124
|
+
missing = paths.reject { |path| @links.key?(path) }
|
|
125
|
+
@links.merge!(LoadCommands.parse(otool(missing), missing)) if missing.any?
|
|
126
|
+
@links.slice(*paths)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def otool(paths)
|
|
131
|
+
output, = Open3.capture2(OTOOL, '-l', *paths, err: File::NULL)
|
|
132
|
+
output
|
|
133
|
+
rescue SystemCallError
|
|
134
|
+
''
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MXC
|
|
4
|
+
# Reads the libraries and run paths of Mach-O files from the load
|
|
5
|
+
# commands <tt>otool -l</tt> lists, with every architecture of a
|
|
6
|
+
# universal file together.
|
|
7
|
+
module LoadCommands # :nodoc:
|
|
8
|
+
LOAD = /\A\s*cmd LC_(?:LOAD_DYLIB|LOAD_WEAK_DYLIB|REEXPORT_DYLIB|LAZY_LOAD_DYLIB|LOAD_UPWARD_DYLIB)\z/
|
|
9
|
+
RPATH = /\A\s*cmd LC_RPATH\z/
|
|
10
|
+
COMMAND = /\A\s*cmd /
|
|
11
|
+
VALUE = /\A\s*(?:name|path) (.+) \(offset \d+\)\z/
|
|
12
|
+
ARCHITECTURE = / \(architecture [^)]+\)\z/
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
# Returns, for each of +paths+, the install names of the libraries it
|
|
16
|
+
# loads and its run paths, as <tt>{ libraries: [...], rpaths: [...] }</tt>.
|
|
17
|
+
def parse(output, paths)
|
|
18
|
+
links = paths.to_h { |path| [path, { libraries: [], rpaths: [] }] }
|
|
19
|
+
current = kind = nil
|
|
20
|
+
output.each_line(chomp: true) do |line|
|
|
21
|
+
if links.key?(header = header_path(line))
|
|
22
|
+
current = links[header]
|
|
23
|
+
kind = nil
|
|
24
|
+
elsif current
|
|
25
|
+
kind = record(current, kind, line)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
links
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def record(links, kind, line)
|
|
34
|
+
return :libraries if line.match?(LOAD)
|
|
35
|
+
return :rpaths if line.match?(RPATH)
|
|
36
|
+
return if line.match?(COMMAND)
|
|
37
|
+
|
|
38
|
+
value = line[VALUE, 1] if kind
|
|
39
|
+
return kind unless value
|
|
40
|
+
|
|
41
|
+
links[kind] << value
|
|
42
|
+
nil
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def header_path(line)
|
|
46
|
+
line.delete_suffix(':').sub(ARCHITECTURE, '') if line.end_with?(':') && !line.start_with?(' ', "\t")
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
data/lib/mxc/sandbox.rb
CHANGED
|
@@ -30,7 +30,8 @@ module MXC
|
|
|
30
30
|
class Sandbox
|
|
31
31
|
BACKENDS = %i[auto bubblewrap landlock seatbelt process_container].freeze # :nodoc:
|
|
32
32
|
LANDLOCK_FALLBACK = /runs on Landlock instead/ # :nodoc:
|
|
33
|
-
OPTIONS = %i[readable writable denied network env directory timeout backend limits
|
|
33
|
+
OPTIONS = %i[readable writable denied libraries libraries_of network env directory timeout backend limits
|
|
34
|
+
priority].freeze # :nodoc:
|
|
34
35
|
HOST_RESOLVER_SOCKETS = %w[/run/systemd/resolve].freeze # :nodoc:
|
|
35
36
|
WINDOWS_ENV = %w[SYSTEMROOT WINDIR SYSTEMDRIVE COMSPEC PATHEXT PATH LOCALAPPDATA TEMP TMP
|
|
36
37
|
PROCESSOR_ARCHITECTURE NUMBER_OF_PROCESSORS OS].freeze # :nodoc:
|
|
@@ -40,8 +41,8 @@ module MXC
|
|
|
40
41
|
PRIORITIES = { normal: nil, low: 'low', lowest: 'idle' }.freeze # :nodoc:
|
|
41
42
|
MEGABYTE = 1024 * 1024 # :nodoc:
|
|
42
43
|
DEFAULTS = {
|
|
43
|
-
readable: [], writable: [], denied: [],
|
|
44
|
-
limits: {}, priority: nil
|
|
44
|
+
readable: [], writable: [], denied: [], libraries: true, libraries_of: [], env: {}, network: false,
|
|
45
|
+
directory: nil, timeout: nil, backend: nil, limits: {}, priority: nil
|
|
45
46
|
}.freeze # :nodoc:
|
|
46
47
|
|
|
47
48
|
class << self
|
|
@@ -54,6 +55,13 @@ module MXC
|
|
|
54
55
|
# Adds paths every instance hides, even inside readable or writable paths.
|
|
55
56
|
def denied(*paths) = configure { |sandbox| sandbox.with_denied(*paths) }
|
|
56
57
|
|
|
58
|
+
# Adds programs and libraries whose shared libraries every instance can load.
|
|
59
|
+
# Takes the same arguments as #with_libraries_of.
|
|
60
|
+
def libraries_of(*paths) = configure { |sandbox| sandbox.with_libraries_of(*paths) }
|
|
61
|
+
|
|
62
|
+
# Sets whether every instance can read the libraries its programs load. See #with_libraries.
|
|
63
|
+
def libraries(enabled) = configure { |sandbox| sandbox.with_libraries(enabled) }
|
|
64
|
+
|
|
57
65
|
# Sets every instance's network access. Takes the same arguments as #with_network.
|
|
58
66
|
def network(...) = configure { |sandbox| sandbox.with_network(...) }
|
|
59
67
|
|
|
@@ -135,6 +143,12 @@ module MXC
|
|
|
135
143
|
# Returns the paths hidden from the command, as given.
|
|
136
144
|
def denied = @settings[:denied].dup.freeze
|
|
137
145
|
|
|
146
|
+
# Returns the programs and libraries whose shared libraries the command can load, as given.
|
|
147
|
+
def libraries_of = @settings[:libraries_of].dup.freeze
|
|
148
|
+
|
|
149
|
+
# Returns true when the command can read the libraries its program loads, the default.
|
|
150
|
+
def libraries = @settings[:libraries]
|
|
151
|
+
|
|
138
152
|
# Returns the environment variables set for the command.
|
|
139
153
|
def env = @settings[:env].dup.freeze
|
|
140
154
|
|
|
@@ -163,7 +177,8 @@ module MXC
|
|
|
163
177
|
add_paths(:readable, paths)
|
|
164
178
|
end
|
|
165
179
|
|
|
166
|
-
# Adds paths the command can read and write.
|
|
180
|
+
# Adds paths the command can read and write. A path that is also #readable is writable,
|
|
181
|
+
# whichever was added first. A readable path inside a writable one stays read-only.
|
|
167
182
|
def with_writable(*paths)
|
|
168
183
|
add_paths(:writable, paths)
|
|
169
184
|
end
|
|
@@ -173,6 +188,32 @@ module MXC
|
|
|
173
188
|
add_paths(:denied, paths)
|
|
174
189
|
end
|
|
175
190
|
|
|
191
|
+
# Adds programs and libraries whose shared libraries the command loads, such as the
|
|
192
|
+
# extensions an interpreter opens. On macOS, the command can read those library files,
|
|
193
|
+
# and the libraries they load in turn, when they are not the system's own. The program
|
|
194
|
+
# the command runs needs no entry: #run grants its libraries already. Elsewhere, on a
|
|
195
|
+
# Mac without the Command Line Tools, and with <tt>with_libraries(false)</tt>, this
|
|
196
|
+
# grants nothing.
|
|
197
|
+
#
|
|
198
|
+
# sandbox.with_libraries_of(*Dir[File.join(RbConfig::CONFIG["archdir"], "**", "*.bundle")])
|
|
199
|
+
def with_libraries_of(*paths)
|
|
200
|
+
add_paths(:libraries_of, paths)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# Sets whether the command can read the shared libraries its program and #libraries_of
|
|
204
|
+
# load, on macOS. +true+ is the default; +false+ grants no library, so the command reads
|
|
205
|
+
# only the system's and those under #readable. +nil+ resets it to +true+.
|
|
206
|
+
#
|
|
207
|
+
# sandbox.with_libraries(false)
|
|
208
|
+
def with_libraries(enabled)
|
|
209
|
+
unless [true, false, nil].include?(enabled)
|
|
210
|
+
raise ArgumentError, "libraries must be true, false or nil, got #{enabled.inspect}"
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
@settings[:libraries] = enabled != false
|
|
214
|
+
self
|
|
215
|
+
end
|
|
216
|
+
|
|
176
217
|
# Sets network access. The default, +false+, gives the command no network at all.
|
|
177
218
|
# +true+ allows any destination. <tt>allow:</tt> takes a list of hosts the command
|
|
178
219
|
# may reach over HTTP and HTTPS: <tt>"pypi.org"</tt>, <tt>"*.pythonhosted.org"</tt>
|
|
@@ -273,6 +314,12 @@ module MXC
|
|
|
273
314
|
#
|
|
274
315
|
# With a block, yields each Chunk of output as it arrives.
|
|
275
316
|
#
|
|
317
|
+
# On macOS, the command can read the shared library files its program links outside
|
|
318
|
+
# the system's own, such as Homebrew's, so programs built against them start. The
|
|
319
|
+
# program is the first argument, or the first word of a command for the shell, found
|
|
320
|
+
# on the +PATH+ of #env. See #with_libraries_of for libraries the program opens later,
|
|
321
|
+
# and #with_libraries to turn this off.
|
|
322
|
+
#
|
|
276
323
|
# sandbox.run("python3 build.py && ls dist")
|
|
277
324
|
# sandbox.run("python3", "convert.py", params[:filename])
|
|
278
325
|
# sandbox.run("python3", "build.py") { |chunk| print chunk.content }
|
|
@@ -283,7 +330,8 @@ module MXC
|
|
|
283
330
|
def run(*command, &)
|
|
284
331
|
return stream(*command, &) if block_given?
|
|
285
332
|
|
|
286
|
-
|
|
333
|
+
arguments = command_arguments(command)
|
|
334
|
+
outcome = StartupFailure.check!(Native.run(command_line(arguments), request(arguments)))
|
|
287
335
|
Result.new(**outcome, backend: resolved_backend(outcome[:warnings]))
|
|
288
336
|
end
|
|
289
337
|
|
|
@@ -292,7 +340,8 @@ module MXC
|
|
|
292
340
|
#
|
|
293
341
|
# sandbox.spawn("python3", "-i", "-q")
|
|
294
342
|
def spawn(*command)
|
|
295
|
-
|
|
343
|
+
arguments = command_arguments(command)
|
|
344
|
+
native = Native.spawn(command_line(arguments), request(arguments))
|
|
296
345
|
Process.new(native, backend: resolved_backend(native.warnings))
|
|
297
346
|
end
|
|
298
347
|
|
|
@@ -315,7 +364,8 @@ module MXC
|
|
|
315
364
|
def inspect # :nodoc:
|
|
316
365
|
resources = " limits=#{limits.inspect} priority=#{priority.inspect}" if self.resources
|
|
317
366
|
"#<#{self.class.name || 'MXC::Sandbox'} backend=#{backend.inspect} network=#{network.inspect} " \
|
|
318
|
-
"readable=#{readable.inspect} writable=#{writable.inspect} timeout=#{timeout.inspect}#{resources}
|
|
367
|
+
"readable=#{readable.inspect} writable=#{writable.inspect} timeout=#{timeout.inspect}#{resources}" \
|
|
368
|
+
"#{libraries_inspect}>"
|
|
319
369
|
end
|
|
320
370
|
|
|
321
371
|
protected
|
|
@@ -330,7 +380,7 @@ module MXC
|
|
|
330
380
|
|
|
331
381
|
def apply(name, value)
|
|
332
382
|
case name
|
|
333
|
-
when :readable, :writable, :denied then public_send(:"with_#{name}", *Array(value))
|
|
383
|
+
when :readable, :writable, :denied, :libraries_of then public_send(:"with_#{name}", *Array(value))
|
|
334
384
|
when :network then value.is_a?(Hash) ? with_network(**value) : with_network(value)
|
|
335
385
|
when :limits then value.nil? ? with_limits(nil) : with_limits(**value)
|
|
336
386
|
else public_send(:"with_#{name}", value)
|
|
@@ -384,8 +434,7 @@ module MXC
|
|
|
384
434
|
process&.kill unless finished
|
|
385
435
|
end
|
|
386
436
|
|
|
387
|
-
def command_line(
|
|
388
|
-
arguments = command_arguments(command)
|
|
437
|
+
def command_line(arguments)
|
|
389
438
|
return command_line_for_windows(arguments) if Preflight.windows?
|
|
390
439
|
|
|
391
440
|
arguments.one? ? arguments.first : Shellwords.join(arguments)
|
|
@@ -420,11 +469,13 @@ module MXC
|
|
|
420
469
|
warnings.any?(LANDLOCK_FALLBACK) ? :landlock : :bubblewrap
|
|
421
470
|
end
|
|
422
471
|
|
|
423
|
-
def request
|
|
472
|
+
def request(arguments)
|
|
424
473
|
Preflight.check!(network:, denied:, resources:, backend:)
|
|
474
|
+
readwrite = expand(writable)
|
|
425
475
|
{
|
|
426
|
-
|
|
427
|
-
|
|
476
|
+
# MXC resolves a path in both lists to read-only.
|
|
477
|
+
readonly: (expand(readable) | library_files(arguments)) - readwrite,
|
|
478
|
+
readwrite:,
|
|
428
479
|
denied: expand(denied) | hidden_resolver_sockets,
|
|
429
480
|
environment:,
|
|
430
481
|
working_directory:,
|
|
@@ -474,6 +525,17 @@ module MXC
|
|
|
474
525
|
system.reject { |name, _| env.keys.any? { |own| own.casecmp?(name) } }.merge(env)
|
|
475
526
|
end
|
|
476
527
|
|
|
528
|
+
def libraries_inspect
|
|
529
|
+
libraries ? (" libraries_of=#{libraries_of.inspect}" if libraries_of.any?) : ' libraries=false'
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
def library_files(arguments)
|
|
533
|
+
return [] unless libraries && Libraries.available?
|
|
534
|
+
|
|
535
|
+
program = Libraries.program(arguments, path: env['PATH'], directory: working_directory)
|
|
536
|
+
Libraries.files([*program, *expand(libraries_of)], executable: program)
|
|
537
|
+
end
|
|
538
|
+
|
|
477
539
|
def hidden_resolver_sockets
|
|
478
540
|
return [] if network == true
|
|
479
541
|
|
data/lib/mxc/version.rb
CHANGED
data/lib/mxc.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mxc
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.1
|
|
5
5
|
platform: x86_64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Carmine Paolino
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-11-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: An unofficial Ruby binding to Microsoft's MXC. Run commands in Bubblewrap,
|
|
14
14
|
Seatbelt or Windows ProcessContainer sandboxes with filesystem, network, environment
|
|
@@ -32,6 +32,8 @@ files:
|
|
|
32
32
|
- lib/mxc/chunk.rb
|
|
33
33
|
- lib/mxc/configuration.rb
|
|
34
34
|
- lib/mxc/error.rb
|
|
35
|
+
- lib/mxc/libraries.rb
|
|
36
|
+
- lib/mxc/load_commands.rb
|
|
35
37
|
- lib/mxc/native.rb
|
|
36
38
|
- lib/mxc/preflight.rb
|
|
37
39
|
- lib/mxc/process.rb
|