From a3cfff72fd6bdef8a7f1388cc04be28375f94839 Mon Sep 17 00:00:00 2001 From: Caleb Xu Date: Sat, 13 Apr 2024 00:25:00 -0400 Subject: [PATCH] formula_installer: conditionally deny network access in sandbox --- Library/Homebrew/formula_installer.rb | 6 ++-- .../Homebrew/test/formula_installer_spec.rb | 6 ++++ .../fixtures/failball_offline_install.rb | 31 +++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 Library/Homebrew/test/support/fixtures/failball_offline_install.rb diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index 4c1503033b..2964234b2b 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -925,7 +925,7 @@ on_request: installed_on_request?, options:) formula.specified_path, ].concat(build_argv) - Utils.safe_fork do + Utils.safe_fork do |error_pipe| if Sandbox.available? sandbox = Sandbox.new formula.logs.mkpath @@ -937,6 +937,7 @@ on_request: installed_on_request?, options:) sandbox.allow_fossil sandbox.allow_write_xcode sandbox.allow_write_cellar(formula) + sandbox.deny_all_network_except_pipe(error_pipe) unless formula.network_access_allowed?(:build) sandbox.exec(*args) else exec(*args) @@ -1151,7 +1152,7 @@ on_request: installed_on_request?, options:) args << post_install_formula_path - Utils.safe_fork do + Utils.safe_fork do |error_pipe| if Sandbox.available? sandbox = Sandbox.new formula.logs.mkpath @@ -1161,6 +1162,7 @@ on_request: installed_on_request?, options:) sandbox.allow_write_xcode sandbox.deny_write_homebrew_repository sandbox.allow_write_cellar(formula) + sandbox.deny_all_network_except_pipe(error_pipe) unless formula.network_access_allowed?(:postinstall) Keg::KEG_LINK_DIRECTORIES.each do |dir| sandbox.allow_write_path "#{HOMEBREW_PREFIX}/#{dir}" end diff --git a/Library/Homebrew/test/formula_installer_spec.rb b/Library/Homebrew/test/formula_installer_spec.rb index 67806d34c6..b09c85e7cf 100644 --- a/Library/Homebrew/test/formula_installer_spec.rb +++ b/Library/Homebrew/test/formula_installer_spec.rb @@ -3,11 +3,13 @@ require "formula" require "formula_installer" require "keg" +require "sandbox" require "tab" require "cmd/install" require "test/support/fixtures/testball" require "test/support/fixtures/testball_bottle" require "test/support/fixtures/failball" +require "test/support/fixtures/failball_offline_install" RSpec.describe FormulaInstaller do matcher :be_poured_from_bottle do @@ -70,6 +72,10 @@ RSpec.describe FormulaInstaller do end end + specify "offline installation" do + expect { temporary_install(FailballOfflineInstall.new) }.to raise_error(BuildError) if Sandbox.available? + end + specify "Formula is not poured from bottle when compiler specified" do temporary_install(TestballBottle.new, cc: "clang") do |f| tab = Tab.for_formula(f) diff --git a/Library/Homebrew/test/support/fixtures/failball_offline_install.rb b/Library/Homebrew/test/support/fixtures/failball_offline_install.rb new file mode 100644 index 0000000000..011b452ae3 --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/failball_offline_install.rb @@ -0,0 +1,31 @@ +# typed: true +# frozen_string_literal: true + +class FailballOfflineInstall < Formula + def initialize(name = "failball_offline_install", path = Pathname.new(__FILE__).expand_path, spec = :stable, + alias_path: nil, tap: nil, force_bottle: false) + super + end + + DSL_PROC = proc do + url "file://#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz" + sha256 TESTBALL_SHA256 + deny_network_access! :build + end.freeze + private_constant :DSL_PROC + + DSL_PROC.call + + def self.inherited(other) + super + other.instance_eval(&DSL_PROC) + end + + def install + system "curl", "example.org" + + prefix.install "bin" + prefix.install "libexec" + Dir.chdir "doc" + end +end