Class: Sandbox::Bubblewrap
- Inherits:
-
LinuxBackend
- Object
- LinuxBackend
- Sandbox::Bubblewrap
- Extended by:
- SystemCommand::Mixin, Utils::Output::Mixin
- Defined in:
- extend/os/linux/sandbox/bubblewrap.rb
Defined Under Namespace
Classes: self
Class Method Summary collapse
- .available? ⇒ Boolean private
- .configuration_command_messages ⇒ Array<String> private
- .configuration_commands ⇒ Array<String> private
- .configure! ⇒ void private
- .ensure_installed!(install_from_tests: false) ⇒ void private
- .executable ⇒ ::Pathname? private
- .executable! ⇒ ::Pathname private
- .executable_candidate_paths ⇒ ::PATH private
- .executable_name ⇒ String private
- .executable_usable?(candidate) ⇒ Boolean private
- .failure_reason ⇒ String? private
- .install_command ⇒ String? private
-
.nested_sandbox? ⇒ Boolean
private
Bubblewrap reports this specific namespace error when an outer Bubblewrap sandbox prevents Homebrew from creating another rootless sandbox.
- .reset_state! ⇒ void private
- .state ⇒ Symbol private
- .system_paths ⇒ Array<String> private
Instance Method Summary collapse
- #arguments(tmpdir) ⇒ Array<String> private
- #command(args, tmpdir) ⇒ Array<String, ::Pathname> private
- #initialize(profile) ⇒ void constructor private
- #run(&block) ⇒ void private
Methods included from SystemCommand::Mixin
system_command, system_command!
Methods included from Utils::Output::Mixin
issue_reporting_message, odebug, odeprecated, odie, odisabled, ofail, oh1, oh1_title, ohai, ohai_title, onoe, opoo, opoo_outside_github_actions, opoo_without_github_actions_annotation, pretty_deprecated, pretty_disabled, pretty_duration, pretty_install_status, pretty_installed, pretty_uninstalled, pretty_unmarked, pretty_upgradable, pretty_warning
Methods inherited from LinuxBackend
full_write_isolation?, #writable_paths
Constructor Details
#initialize(profile) ⇒ void
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
290 291 292 293 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 290 def initialize(profile) super @masked_read_paths = T.let([], T::Array[::Pathname]) end |
Class Method Details
.available? ⇒ Boolean
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
156 157 158 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 156 def available? state == :available end |
.configuration_command_messages ⇒ Array<String>
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
196 197 198 199 200 201 202 203 204 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 196 def commands = configuration_commands SYSCTL_SETTINGS.each_with_index.flat_map do |setting, index| [ " #{commands.fetch(index)}", *setting.description.map { |line| " #{line}" }, ] end end |
.configuration_commands ⇒ Array<String>
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
187 188 189 190 191 192 193 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 187 def configuration_commands SYSCTL_SETTINGS.map do |setting| command = "sudo sysctl -w #{setting.assignment}" command += " || true" if setting.optional command end end |
.configure! ⇒ void
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
This method returns an undefined value.
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 207 def configure! unless executable ensure_installed!(install_from_tests: true) unless executable reset_state! return end end ohai "Configuring Bubblewrap..." command = [HOMEBREW_BREW_FILE.to_s, "setup-sandbox"] command.unshift("sudo") unless Process.euid.zero? raise ErrorDuringExecution.new(command, status: $CHILD_STATUS || 1) unless system(*command) reset_state! end |
.ensure_installed!(install_from_tests: false) ⇒ void
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
This method returns an undefined value.
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 126 def ensure_installed!(install_from_tests: false) return unless Homebrew::EnvConfig.sandbox_linux? return if ENV["HOMEBREW_TESTS"] && !install_from_tests return if ENV["HOMEBREW_INSTALLING_BUBBLEWRAP"] return if executable begin require "exceptions" require "formula" with_env(HOMEBREW_INSTALLING_BUBBLEWRAP: "1") do ::Formula["bubblewrap"].ensure_installed!(reason: "Linux sandboxing") end reset_state! return if executable rescue ::FormulaUnavailableError nil end return unless GitHub::Actions.env_set? return unless ENV.fetch("HOMEBREW_GITHUB_HOSTED_RUNNER", nil) return unless which("apt-get") ohai "Installing Bubblewrap..." command = ["apt-get", "install", "--yes", "bubblewrap"] command.unshift("sudo") unless Process.euid.zero? system(*command) reset_state! end |
.executable ⇒ ::Pathname?
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 103 def executable executable_candidate_paths.each do |path| begin candidate = ::Pathname.new(File.(executable_name, path)) rescue ArgumentError next end next if !candidate.file? || !candidate.executable? next unless executable_usable?(candidate) return candidate end nil end |
.executable! ⇒ ::Pathname
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
121 122 123 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 121 def executable! executable || raise("Bubblewrap is required to use the Linux sandbox.") end |
.executable_candidate_paths ⇒ ::PATH
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
98 99 100 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 98 def executable_candidate_paths PATH.new(HOMEBREW_PATHS, system_paths, ORIGINAL_PATHS, ENV.fetch("PATH"), HOMEBREW_ORIGINAL_BREW_FILE.dirname) end |
.executable_name ⇒ String
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
83 84 85 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 83 def executable_name EXECUTABLE end |
.executable_usable?(candidate) ⇒ Boolean
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
88 89 90 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 88 def executable_usable?(candidate) !File.stat(candidate).setuid? end |
.failure_reason ⇒ String?
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 225 def failure_reason case state when :config_disabled, :available nil when :missing "Bubblewrap is required to use the Linux sandbox but was not found." when :setuid "A rootless Bubblewrap executable is required to use the Linux sandbox, " \ "but all found `bwrap` executables are setuid." when :unavailable "Bubblewrap is installed but cannot create a rootless sandbox." else "The Linux sandbox is not available." end end |
.install_command ⇒ String?
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
242 243 244 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 242 def install_command INSTALL_COMMANDS.find { |package_manager, _| which(package_manager) }&.last end |
.nested_sandbox? ⇒ Boolean
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
Bubblewrap reports this specific namespace error when an outer
Bubblewrap sandbox prevents Homebrew from creating another rootless
sandbox. The shared avoid_nested_sandboxing? only calls this once the
$HOMEBREW_AVOID_NESTED_SANDBOXING opt-in is set.
165 166 167 168 169 170 171 172 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 165 def nested_sandbox? return false unless Homebrew::EnvConfig.sandbox_linux? bubblewrap = executable return false unless bubblewrap Utils.popen_read(bubblewrap.to_s, *TEST_ARGS, err: :out).include?(NESTED_ERROR) end |
.reset_state! ⇒ void
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
This method returns an undefined value.
182 183 184 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 182 def reset_state! @state = T.let(nil, T.nilable(Symbol)) end |
.state ⇒ Symbol
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
175 176 177 178 179 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 175 def state return :config_disabled unless Homebrew::EnvConfig.sandbox_linux? @state ||= T.let(compute_state, T.nilable(Symbol)) end |
.system_paths ⇒ Array<String>
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
93 94 95 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 93 def system_paths SYSTEM_PATHS end |
Instance Method Details
#arguments(tmpdir) ⇒ Array<String>
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 312 def arguments(tmpdir) args = T.let([ "--unshare-user", "--unshare-ipc", "--unshare-pid", "--unshare-uts", "--unshare-cgroup-try", "--die-with-parent", "--new-session", "--ro-bind", "/", "/", "--dev", "/dev", "--proc", "/proc" ], T::Array[String]) args << "--unshare-net" if deny_all_network? writable_paths.each do |path, type| prepare_writable_path(path, type) args += ["--bind", path, path] end denied_write_paths.each do |path| next unless File.exist?(path) args += ["--ro-bind", path, path] end denied_read_paths.each do |path| next unless File.exist?(path) args += if File.directory?(path) ["--bind", masked_read_path, path] else ["--ro-bind", File::NULL, path] end end args += ["--bind", tmpdir, tmpdir, "--chdir", tmpdir] args end |
#command(args, tmpdir) ⇒ Array<String, ::Pathname>
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
307 308 309 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 307 def command(args, tmpdir) [self.class.executable!, *arguments(tmpdir), "--", *args] end |
#run(&block) ⇒ void
This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.
This method returns an undefined value.
296 297 298 299 300 301 302 303 304 |
# File 'extend/os/linux/sandbox/bubblewrap.rb', line 296 def run(&block) old_report_on_exception = T.let(Thread.report_on_exception, T.nilable(T::Boolean)) Thread.report_on_exception = false super ensure Thread.report_on_exception = old_report_on_exception unless old_report_on_exception.nil? @masked_read_paths.reverse_each { |path| FileUtils.rm_rf(path) } @masked_read_paths.clear end |