bwrap 1.0.0.pre.alpha5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dfb5f9bdbcf68df6068aebca204e72ef9272829b1f8db11c34e5a4da469cc2c7
4
- data.tar.gz: 5f19c25ecad9b7f4923f80a6d61c87c6382671667f6b39eed0198befbb8eccd2
3
+ metadata.gz: e422d8c89dbcf1a803b89532b1214745f558faceaa5dc997ed2487bf92912010
4
+ data.tar.gz: 1e265d4aaeb7e05e2b4ff5d8d5f490afb4be04287c0aaeaedc96abf4f2f1022e
5
5
  SHA512:
6
- metadata.gz: c9682aff2b43180fee0e8d7b2b7234d4bb516e86c85dcabc5b40a1047284f9f5bf9e0641dff80483e4645b8aa4bd06c9b9de8ba1b43cd78af3b77de1060c8ad6
7
- data.tar.gz: cadd731077ff175b86cf0d56f17dd1c2cb3123e5d9b1dcff17156da5d706d7da12274bc59297ae925c1f07ea5b3a325c999c942048c2c5b165755934ae16d2f8
6
+ metadata.gz: 86198210a21a75e373e15341d564fc0941d08066d5272b454b64530e3bcce951f0e402c4a9a9f7e34f60d76fbe72140aabab40637e539ec2ef2412a60ebf0f77
7
+ data.tar.gz: 2aa60e671d0e8da2fb2d59cf68bc3043d350b557e16c0b81b8a1e62240f24f2d44dfb143b7fb66ab50bac9e51122865326d2290138b35506cd6a6bdabe2b4402
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # Changes
2
2
 
3
+ ## 1.0.0 (16.04.2022)
4
+
5
+ * Handle invalid output to loggers
6
+
7
+ ## 1.0.0-beta2 (02.02.2022)
8
+
9
+ * Added nscd feature
10
+ * Added gem_env_paths to ruby feature
11
+ * If Config#root is set, set working directory to /
12
+ * Execution#execvalue: Allow setting log: true
13
+ * Execution#execvalue: pass all kwargs as kwargs to execute()
14
+ * Output::Log: Don’t die if log file can’t be written to
15
+
16
+ ## 1.0.0-beta1 (12.12.2021)
17
+
18
+ * optimist gem is now optional dependency
19
+ * Added Config#env_paths and Config#add_env_path
20
+ * Added Config#command_inside_root
21
+ * Added Bwrap#run_inside_root convenience method
22
+ * Execution#command_available?: added env_path_var argument
23
+ * Execution#which: added env_path_var argument
24
+ * Be able to resolve /usr/bin/env to real executable
25
+ * Try to avoid duplicate library binds
26
+ * Added Config#extra_executables
27
+ * Added Config::Features::Bash
28
+
3
29
  ## 1.0.0-alpha5 (29.11.2021)
4
30
 
5
31
  * Execution#command_available?: support absolute paths
@@ -2,7 +2,11 @@
2
2
 
3
3
  require "bwrap/version"
4
4
 
5
- # bwrap argument related operations.
5
+ # Classes that are used for building arguments.
6
+ #
7
+ # @note Classes inside here are kind of pseudo-internal API.
8
+ # In future, there may be some use for classes inside here, but for now they are
9
+ # only used internally.
6
10
  module Bwrap::Args
7
11
  # Nya.
8
12
  end
@@ -0,0 +1,188 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bwrap/execution/path"
4
+ require "bwrap/output"
5
+ require_relative "../library"
6
+ require_relative "mime"
7
+
8
+ class Bwrap::Args::Bind
9
+ # TODO: documentation
10
+ #
11
+ # TODO: It may be that this should be renamed to “Binary” or ”Executable”, as this
12
+ # handles all binaries, not just libraries.
13
+ #
14
+ # @api private
15
+ class Library
16
+ include Bwrap::Execution::Path
17
+ include Bwrap::Output
18
+
19
+ # @see Bwrap::Args::Construct#command=
20
+ #
21
+ # @see (see Bwrap::Args::Construct#command=)
22
+ attr_writer :command
23
+
24
+ # Instance of {Bwrap::Config}.
25
+ attr_writer :config
26
+
27
+ # Instance of {Bwrap::Args::Environment}.
28
+ attr_writer :environment
29
+
30
+ attr_writer :executable_name
31
+
32
+ attr_writer :executable_path
33
+
34
+ # Ruby feature implementation specific class.
35
+ #
36
+ # @api private
37
+ class RubyBinds
38
+ # Instance of {Bwrap::Config}.
39
+ attr_writer :config
40
+
41
+ def initialize args
42
+ @args = args
43
+ end
44
+
45
+ def ruby_binds_for_features
46
+ return unless @config and @config.features.ruby.enabled?
47
+
48
+ @mounts = []
49
+
50
+ # Mount some common Ruby executables.
51
+
52
+ # This is most often /usr/bin.
53
+ bindir = Pathname.new RbConfig::CONFIG["bindir"]
54
+
55
+ path = bindir / "ruby"
56
+ if File.exist? path
57
+ @mounts << "--ro-bind" << path.to_s << path.to_s
58
+ end
59
+
60
+ gem_binds bindir
61
+
62
+ @args += @mounts
63
+ end
64
+
65
+ private def gem_binds bindir
66
+ return unless @config.features.ruby.gem_env_paths?
67
+
68
+ path = bindir / "gem"
69
+ return unless File.exist? path
70
+
71
+ @mounts << "--ro-bind" << path.to_s << path.to_s
72
+ end
73
+ end
74
+
75
+ def initialize args
76
+ @args = args
77
+ end
78
+
79
+ def extra_executables_mounts
80
+ return unless @config&.extra_executables
81
+
82
+ @config.extra_executables.each do |executable|
83
+ @executable_name = resolve_executable_name executable
84
+ @executable_path = resolve_executable_path @executable_name, not_inside_root: true
85
+
86
+ @args.append %W{ --ro-bind #{@executable_path} #{@executable_path} }
87
+
88
+ resolve_executable_libraries
89
+ end
90
+ end
91
+
92
+ # Convenience method to call {#resolve_executable_libraries}.
93
+ #
94
+ # Used by {#handle_system_mounts}.
95
+ def libs_command_requires
96
+ @executable_name = resolve_executable_name @command
97
+ @executable_path = resolve_executable_path @executable_name
98
+
99
+ # Actually add the executable to be bound to the sandbox.
100
+ unless @config&.command_inside_root
101
+ @args.append %W{ --ro-bind #{@executable_path} #{@executable_path} }
102
+ end
103
+
104
+ resolve_executable_libraries
105
+ end
106
+
107
+ # Does some inspection to find out libraries given executable needs in order to work.
108
+ #
109
+ # @warning scanelf does not play with spaces in names well. This method assumes that libraries
110
+ # have no spaces in names, though binaries can have.
111
+ #
112
+ # @todo Ensure scanelf is available (and throw proper error if it is not, telling to not use
113
+ # full_system_mounts option.)
114
+ def resolve_executable_libraries
115
+ trace "Resolving executable libraries of #{@executable_path}"
116
+
117
+ # TODO: Put this behind additional flag for extra control/sanity.
118
+ # Some executables are shell scripts and similar. For them we need to use the interpreter.
119
+
120
+ mime = Mime.new @executable_name, @executable_path
121
+ return unless mime.resolve_mime_type
122
+
123
+ # Then find out required libraries
124
+
125
+ library_mounts = []
126
+
127
+ library_object = ::Bwrap::Args::Library.new
128
+ libraries = library_object.libraries_needed_by mime.executable_path
129
+
130
+ # TODO: following is bad?
131
+ #library_object.needed_libraries(mime.executable_path).each do |library|
132
+ libraries.each do |library|
133
+ library_mounts << "--ro-bind" << library << library
134
+ end
135
+
136
+ @args.append library_mounts
137
+ end
138
+
139
+ # Some features, like {Bwrap::Config::Features::Nscd}, requires some binds
140
+ # in order to operate properly.
141
+ def binds_for_features
142
+ # NOTE: Still nothing here, as I think this is better for library binds than anything else.
143
+ # The nscd bind is better in another, more generic, place.
144
+ #
145
+ # Keeping this method because I think this really makes sense for structure, in future.
146
+
147
+ ruby_binds_for_features
148
+ end
149
+
150
+ # Used by {#libs_command_requires}.
151
+ private def resolve_executable_name command
152
+ if command.is_a? String
153
+ return command
154
+ end
155
+
156
+ # Array-like.
157
+ if command.respond_to? :at
158
+ return command.at(0)
159
+ end
160
+
161
+ raise "Can’t recognize type of given command. Type: #{command.class}"
162
+ end
163
+
164
+ # @warning Requires environment paths to be resolved beforehand.
165
+ #
166
+ # Used by {#libs_command_requires}.
167
+ private def resolve_executable_path executable_name, not_inside_root: nil
168
+ if @config&.command_inside_root.nil? or not_inside_root
169
+ return which executable_name
170
+ end
171
+
172
+ paths = @environment.env_paths.map do |path|
173
+ "#{@config.root}/#{path}"
174
+ end
175
+ env_path = paths.join ":"
176
+
177
+ which executable_name, env_path_var: env_path
178
+ end
179
+
180
+ private def ruby_binds_for_features
181
+ return unless @config.features.ruby.enabled?
182
+
183
+ binds = RubyBinds.new @args
184
+ binds.config = @config
185
+ binds.ruby_binds_for_features
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bwrap/execution"
4
+ require "bwrap/output"
5
+
6
+ class Bwrap::Args::Bind
7
+ # Inner class to clean up namespace for implementation specific reasons.
8
+ #
9
+ # @api private
10
+ class Mime
11
+ include Bwrap::Execution
12
+ include Bwrap::Output
13
+
14
+ # Name given to {#initialize}.
15
+ attr_reader :executable_name
16
+
17
+ # Either path given to {#initialize} or one parsed from shebang.
18
+ attr_reader :executable_path
19
+
20
+ def initialize executable_name, executable_path
21
+ @executable_name = executable_name
22
+ @executable_path = executable_path
23
+ end
24
+
25
+ # Used by {Bwrap::Args::Bind::Library#libs_command_requires}.
26
+ #
27
+ # @return false if caller should also return
28
+ def resolve_mime_type
29
+ mime_type = execvalue %W{ file --brief --mime-type #{@executable_path} }
30
+ trace "Mime type of #{@executable_path} is #{mime_type}"
31
+ return true unless mime_type[0..6] == "text/x-"
32
+
33
+ shebang = File.open @executable_path, &:readline
34
+ if shebang[0..1] != "#!"
35
+ warn "Executable #{@executable_name} was recognized as #{mime_type} but does not have " \
36
+ "proper shebang line. Skipping automatic library mounts."
37
+ return false
38
+ end
39
+
40
+ resolve_real_executable shebang
41
+
42
+ true
43
+ end
44
+
45
+ private def resolve_real_executable shebang
46
+ command_line = shebang.delete_prefix("#!").strip
47
+ real_executable, args = command_line.split " ", 2
48
+
49
+ if [ "/usr/bin/env", "/bin/env" ].include? real_executable
50
+ # First argument is name of the executable, resolved from PATH.
51
+ executable_name = args.split(" ", 2).first
52
+ real_executable = which executable_name
53
+ end
54
+
55
+ @executable_path = real_executable
56
+ end
57
+ end
58
+ end
@@ -3,7 +3,7 @@
3
3
  require "bwrap/execution"
4
4
  require "bwrap/output"
5
5
  require_relative "args"
6
- require_relative "library"
6
+ require_relative "bind/library"
7
7
 
8
8
  # Bind arguments for bwrap.
9
9
  class Bwrap::Args::Bind
@@ -18,52 +18,12 @@ class Bwrap::Args::Bind
18
18
  # @see (see Bwrap::Args::Construct#command=)
19
19
  attr_writer :command
20
20
 
21
- # Instance of {Config}.
21
+ # Instance of {Bwrap::Config}.
22
22
  attr_writer :config
23
23
 
24
24
  # Instance of {Bwrap::Args::Environment}.
25
25
  attr_writer :environment
26
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
-
67
27
  # Arguments to bind /dev/dri from host to sandbox.
68
28
  def bind_dev_dri
69
29
  @args.append %w{ --dev-bind /dev/dri /dev/dri }
@@ -99,13 +59,13 @@ class Bwrap::Args::Bind
99
59
  end
100
60
 
101
61
  # Arguments to read-only bind whole system inside sandbox.
102
- def full_system_mounts
62
+ def handle_system_mounts
103
63
  bindir_mounts = []
104
64
  binaries_from = @config.binaries_from
105
65
  binaries_from.each do |path|
106
66
  bindir_mounts << "--ro-bind" << path << path
107
67
  end
108
- @environment["PATH"] = binaries_from.join(":")
68
+ @environment.add_to_path binaries_from
109
69
 
110
70
  @args.append bindir_mounts
111
71
 
@@ -117,10 +77,15 @@ class Bwrap::Args::Bind
117
77
 
118
78
  libdir_mounts
119
79
 
80
+ library_bind = construct_library_bind
81
+
82
+ binds_for_features
83
+ library_bind.binds_for_features
84
+ library_bind.extra_executables_mounts
85
+
120
86
  return unless @config.full_system_mounts
121
87
 
122
- loader_binds
123
- libs_command_requires
88
+ library_bind.libs_command_requires
124
89
  end
125
90
 
126
91
  # These are something user can specify to do custom --ro-bind binds.
@@ -132,10 +97,15 @@ class Bwrap::Args::Bind
132
97
  binds << "--ro-bind" << source_path.to_s << destination_path.to_s
133
98
  end
134
99
 
135
- @args.append binds
100
+ @args.append binds unless binds.empty?
101
+ end
102
+
103
+ # Performs cleanup operations after execution.
104
+ def cleanup
105
+ Bwrap::Args::Library.clear_needed_libraries_cache
136
106
  end
137
107
 
138
- # Used by {#full_system_mounts}.
108
+ # Used by {#handle_system_mounts}.
139
109
  private def libdir_mounts
140
110
  return unless @config.libdir_mounts
141
111
 
@@ -155,49 +125,17 @@ class Bwrap::Args::Bind
155
125
  @args.append libdir_mounts
156
126
  end
157
127
 
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
128
+ private def construct_library_bind
129
+ library_bind = Bwrap::Args::Bind::Library.new @args
130
+ library_bind.command = @command
131
+ library_bind.config = @config
132
+ library_bind.environment = @environment
165
133
 
166
- @args.append loader_mounts
134
+ library_bind
167
135
  end
168
136
 
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
199
- end
200
-
201
- @args.append library_mounts
137
+ # Binds feature specific common directories.
138
+ private def binds_for_features
139
+ # Nya.
202
140
  end
203
141
  end
@@ -22,7 +22,7 @@ class Bwrap::Args::Construct
22
22
  # setting {Config#full_system_mounts=} uses this to resolve some
23
23
  # additional data.
24
24
  #
25
- # @param command [Array, String] Command with arguments
25
+ # @param value [Array, String] Command with arguments
26
26
  attr_writer :command
27
27
 
28
28
  # Constructs arguments for bwrap execution.
@@ -35,7 +35,7 @@ class Bwrap::Args::Construct
35
35
  machine_id = @machine_id.machine_id
36
36
  @args.append machine_id if machine_id
37
37
  resolv_conf
38
- @bind.full_system_mounts
38
+ @bind.handle_system_mounts
39
39
  @features.feature_binds
40
40
  @bind.custom_read_only_binds
41
41
  create_user_dir
@@ -60,6 +60,7 @@ class Bwrap::Args::Construct
60
60
  # Performs cleanup operations after execution.
61
61
  def cleanup
62
62
  @machine_id&.cleanup
63
+ @bind&.cleanup
63
64
  end
64
65
 
65
66
  # Used by {#construct_bwrap_args}.
@@ -1,24 +1,82 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "bwrap/execution"
3
4
  require "bwrap/output"
4
5
  require_relative "args"
5
6
 
6
7
  # Environment variable calculation for bwrap.
7
8
  class Bwrap::Args::Environment < Hash
9
+ include Bwrap::Execution
8
10
  include Bwrap::Output
9
11
 
10
12
  # Instance of {Config}.
11
13
  attr_writer :config
12
14
 
13
- # Returns used environment variables.
15
+ def initialize
16
+ super
17
+
18
+ self["PATH"] ||= []
19
+ end
20
+
21
+ # Returns used environment variables wrapped as bwrap arguments.
14
22
  def environment_variables
15
23
  if debug?
16
24
  debug "Passing following environment variables to bwrap:\n" \
17
25
  "#{self}"
18
26
  end
19
27
 
28
+ env_paths
29
+
20
30
  map do |key, value|
31
+ if key == "PATH" and value.respond_to? :join
32
+ value = value.join ":"
33
+ end
34
+
21
35
  [ "--setenv", key, value ]
22
36
  end
23
37
  end
38
+
39
+ # @return [Array] All environment paths added via {Config#add_env_path} and other parsing logic
40
+ def env_paths
41
+ if @config.env_paths.respond_to? :each
42
+ self["PATH"] |= @config.env_paths
43
+ end
44
+
45
+ features_env_paths
46
+
47
+ self["PATH"]
48
+ end
49
+
50
+ # Adds given paths to PATH environment variable defined in the sandbox.
51
+ #
52
+ # @param elements [String, Array] Path(s) to be added added to PATH environment variable
53
+ def add_to_path elements
54
+ if elements.respond_to? :each
55
+ self["PATH"] += elements
56
+ else
57
+ # Expecting elements to be single path element as a string.
58
+ self["PATH"] << elements
59
+ end
60
+ end
61
+
62
+ # Feature specific environment path handling.
63
+ private def features_env_paths
64
+ ruby_env_paths
65
+ end
66
+
67
+ # Ruby feature specific environment path handling.
68
+ private def ruby_env_paths
69
+ return unless @config.features.ruby.enabled?
70
+ return unless @config.features.ruby.gem_env_paths?
71
+
72
+ unless command_available? "gem"
73
+ warn "gem is not installed in the system, so can’t add its bindirs to PATH."
74
+ return
75
+ end
76
+
77
+ gempath = execvalue %w{ gem environment gempath }
78
+ gempath.split(":").each do |path|
79
+ self["PATH"] << "#{path}/bin"
80
+ end
81
+ end
24
82
  end
@@ -10,8 +10,46 @@ require_relative "library"
10
10
  class Bwrap::Args::Features < Hash
11
11
  include Bwrap::Output
12
12
 
13
- # @api internal
13
+ # Implementation for Bash feature set.
14
+ #
15
+ # @api private
16
+ class BashBinds
17
+ # Mounts stuff like /bin/bash.
18
+ def bash_mounts
19
+ mounts = []
20
+
21
+ if File.file? "/bin/bash"
22
+ mounts << "--ro-bind" << "/bin/bash" << "/bin/bash"
23
+ end
24
+ if File.file? "/usr/bin/bash"
25
+ mounts << "--ro-bind" << "/usr/bin/bash" << "/usr/bin/bash"
26
+ end
27
+
28
+ mounts
29
+ end
30
+ end
31
+
32
+ # Implementation for nscd feature set.
33
+ #
34
+ # @api private
35
+ class NscdBinds
36
+ # Custom binds needed by the feature.
37
+ def custom_binds
38
+ mounts = []
39
+
40
+ # TODO: Probably some path checking is needed here. Or somewhere.
41
+ # TODO: Since on many systems /var/run is symlinked to /run, that probably should be handled.
42
+ mounts << "--ro-bind" << "/var/run/nscd" << "/var/run/nscd"
43
+
44
+ mounts
45
+ end
46
+ end
47
+
48
+ # Implementation for Ruby feature set.
49
+ #
50
+ # @api private
14
51
  class RubyBinds
52
+ # Returns mounts needed by Ruby feature set.
15
53
  attr_reader :mounts
16
54
 
17
55
  # Bind system paths so scripts works inside sandbox.
@@ -40,19 +78,43 @@ class Bwrap::Args::Features < Hash
40
78
  library_mounts << "--ro-bind" << requisite_library << requisite_library
41
79
  end
42
80
  end
81
+
82
+ library_mounts
43
83
  end
44
84
  end
45
85
 
46
- # {Array} of parameters passed to bwrap.
86
+ # `Array` of parameters passed to bwrap.
47
87
  attr_writer :args
48
88
 
49
89
  # Instance of {Config}.
50
90
  attr_writer :config
51
91
 
92
+ # Resolves binds required by different features.
93
+ #
94
+ # Currently implemented feature sets:
95
+ # - ruby
52
96
  def feature_binds
97
+ bash_binds
98
+ nscd_binds
53
99
  ruby_binds
54
100
  end
55
101
 
102
+ private def bash_binds
103
+ return unless @config.features.bash.enabled?
104
+
105
+ binds = BashBinds.new
106
+
107
+ @args.append binds.bash_mounts
108
+ end
109
+
110
+ private def nscd_binds
111
+ return unless @config.features.nscd.enabled?
112
+
113
+ binds = NscdBinds.new
114
+
115
+ @args.append binds.custom_binds
116
+ end
117
+
56
118
  # @note This does not allow development headers needed for compilation for now.
57
119
  # I’ll look at it after I have an use for it.
58
120
  private def ruby_binds
@@ -61,6 +123,6 @@ class Bwrap::Args::Features < Hash
61
123
  binds = RubyBinds.new
62
124
 
63
125
  @args.append binds.sitedir_mounts
64
- @args.append binds.stdlib_mounts @config.features.ruby.stdlib
126
+ @args.append binds.stdlib_mounts(@config.features.ruby.stdlib)
65
127
  end
66
128
  end