bwrap 1.0.0.pre.alpha5 → 1.0.0

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 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