brew.sh: enforce HOMEBREW_FORCE_BREW_WRAPPER more strictly
				
					
				
			`HOMEBREW_FORCE_BREW_WRAPPER` can be used as a security/compliance feature, but allowing it to be disabled by setting `HOMEBREW_NO_FORCE_BREW_WRAPPER` leaves a pretty large hole in it that allows it to be sidestepped. Let's fix that by actually checking the path of the process that called `brew`, and the verify that that path matches the configured value of `HOMEBREW_NO_FORCE_BREW_WRAPPER`.
This commit is contained in:
		
							parent
							
								
									d7c1336f51
								
							
						
					
					
						commit
						a7c124c2d0
					
				@ -190,35 +190,32 @@ esac
 | 
			
		||||
# Include some helper functions.
 | 
			
		||||
source "${HOMEBREW_LIBRARY}/Homebrew/utils/helpers.sh"
 | 
			
		||||
 | 
			
		||||
# Require HOMEBREW_BREW_WRAPPER to be set if HOMEBREW_FORCE_BREW_WRAPPER is set
 | 
			
		||||
# (and HOMEBREW_NO_FORCE_BREW_WRAPPER is not set) for all non-trivial commands
 | 
			
		||||
# (i.e. not defined above this line e.g. formulae or --cellar).
 | 
			
		||||
if [[ -z "${HOMEBREW_NO_FORCE_BREW_WRAPPER:-}" && -n "${HOMEBREW_FORCE_BREW_WRAPPER:-}" ]]
 | 
			
		||||
# If HOMEBREW_FORCE_BREW_WRAPPER is set, verify that the path to our parent
 | 
			
		||||
# process is the same as the value of HOMEBREW_FORCE_BREW_WRAPPER for all
 | 
			
		||||
# non-trivial commands (i.e. not defined above this line e.g. formulae or --cellar).
 | 
			
		||||
if [[ -n "${HOMEBREW_FORCE_BREW_WRAPPER:-}" ]]
 | 
			
		||||
then
 | 
			
		||||
  HOMEBREW_FORCE_BREW_WRAPPER_WITHOUT_BREW="${HOMEBREW_FORCE_BREW_WRAPPER%/brew}"
 | 
			
		||||
  if [[ -z "${HOMEBREW_BREW_WRAPPER:-}" ]]
 | 
			
		||||
  if [[ -n "${HOMEBREW_MACOS:-}" ]]
 | 
			
		||||
  then
 | 
			
		||||
    source "${HOMEBREW_LIBRARY}/Homebrew/utils/ruby.sh"
 | 
			
		||||
    setup-ruby-path
 | 
			
		||||
    HOMEBREW_BREW_CALLER="$("${HOMEBREW_RUBY_PATH}" "${HOMEBREW_LIBRARY}/Homebrew/utils/pid_path.rb" "${PPID}")"
 | 
			
		||||
  else
 | 
			
		||||
    HOMEBREW_BREW_CALLER="$(readlink -f "/proc/${PPID}/exe")"
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if [[ "${HOMEBREW_BREW_CALLER:-}" != "${HOMEBREW_FORCE_BREW_WRAPPER}" ]]
 | 
			
		||||
  then
 | 
			
		||||
    HOMEBREW_FORCE_BREW_WRAPPER_WITHOUT_BREW="${HOMEBREW_FORCE_BREW_WRAPPER%/brew}"
 | 
			
		||||
 | 
			
		||||
    # HOMEBREW_ORIGINAL_BREW_FILE set by bin/brew
 | 
			
		||||
    # shellcheck disable=SC2154
 | 
			
		||||
    odie <<EOS
 | 
			
		||||
conflicting Homebrew wrapper configuration!
 | 
			
		||||
HOMEBREW_FORCE_BREW_WRAPPER was set to ${HOMEBREW_FORCE_BREW_WRAPPER}
 | 
			
		||||
but   HOMEBREW_BREW_WRAPPER was unset.
 | 
			
		||||
but \`brew\` was invoked by ${HOMEBREW_BREW_CALLER}.
 | 
			
		||||
 | 
			
		||||
$(bold "Ensure you run ${HOMEBREW_FORCE_BREW_WRAPPER} directly (not ${HOMEBREW_BREW_FILE})")!
 | 
			
		||||
 | 
			
		||||
Manually setting your PATH can interfere with Homebrew wrappers.
 | 
			
		||||
Ensure your shell configuration contains:
 | 
			
		||||
  eval "\$(${HOMEBREW_BREW_FILE} shellenv)"
 | 
			
		||||
or that ${HOMEBREW_FORCE_BREW_WRAPPER_WITHOUT_BREW} comes before ${HOMEBREW_PREFIX}/bin in your PATH:
 | 
			
		||||
  export PATH="${HOMEBREW_FORCE_BREW_WRAPPER_WITHOUT_BREW}:${HOMEBREW_PREFIX}/bin:\$PATH"
 | 
			
		||||
EOS
 | 
			
		||||
  elif [[ "${HOMEBREW_FORCE_BREW_WRAPPER}" != "${HOMEBREW_BREW_WRAPPER}" ]]
 | 
			
		||||
  then
 | 
			
		||||
    odie <<EOS
 | 
			
		||||
conflicting Homebrew wrapper configuration!
 | 
			
		||||
HOMEBREW_FORCE_BREW_WRAPPER was set to ${HOMEBREW_FORCE_BREW_WRAPPER}
 | 
			
		||||
but HOMEBREW_BREW_WRAPPER   was set to ${HOMEBREW_BREW_WRAPPER}
 | 
			
		||||
 | 
			
		||||
$(bold "Ensure you run ${HOMEBREW_FORCE_BREW_WRAPPER} directly (not ${HOMEBREW_BREW_FILE})")!
 | 
			
		||||
$(bold "Ensure you run ${HOMEBREW_FORCE_BREW_WRAPPER} directly (not ${HOMEBREW_ORIGINAL_BREW_FILE})")!
 | 
			
		||||
 | 
			
		||||
Manually setting your PATH can interfere with Homebrew wrappers.
 | 
			
		||||
Ensure your shell configuration contains:
 | 
			
		||||
@ -227,6 +224,8 @@ or that ${HOMEBREW_FORCE_BREW_WRAPPER_WITHOUT_BREW} comes before ${HOMEBREW_PREF
 | 
			
		||||
  export PATH="${HOMEBREW_FORCE_BREW_WRAPPER_WITHOUT_BREW}:${HOMEBREW_PREFIX}/bin:\$PATH"
 | 
			
		||||
EOS
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  unset HOMEBREW_BREW_CALLER
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# commands that take a single or no arguments and need to write to HOMEBREW_PREFIX.
 | 
			
		||||
 | 
			
		||||
@ -245,7 +245,6 @@ module Homebrew
 | 
			
		||||
        ENV["HOMEBREW_TEST_GENERIC_OS"] = "1" if args.generic?
 | 
			
		||||
        ENV["HOMEBREW_TEST_ONLINE"] = "1" if args.online?
 | 
			
		||||
        ENV["HOMEBREW_SORBET_RUNTIME"] = "1"
 | 
			
		||||
        ENV["HOMEBREW_NO_FORCE_BREW_WRAPPER"] = "1"
 | 
			
		||||
 | 
			
		||||
        ENV["USER"] ||= system_command!("id", args: ["-nu"]).stdout.chomp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -87,9 +87,6 @@ module Homebrew
 | 
			
		||||
        description: "Use this URL as the Homebrew/brew `git`(1) remote.",
 | 
			
		||||
        default:     HOMEBREW_BREW_DEFAULT_GIT_REMOTE,
 | 
			
		||||
      },
 | 
			
		||||
      HOMEBREW_BREW_WRAPPER:                     {
 | 
			
		||||
        description: "If set, use wrapper to call `brew` rather than auto-detecting it.",
 | 
			
		||||
      },
 | 
			
		||||
      HOMEBREW_BROWSER:                          {
 | 
			
		||||
        description:  "Use this as the browser when opening project homepages.",
 | 
			
		||||
        default_text: "`$BROWSER` or the OS's default browser.",
 | 
			
		||||
@ -263,7 +260,7 @@ module Homebrew
 | 
			
		||||
        boolean:     true,
 | 
			
		||||
      },
 | 
			
		||||
      HOMEBREW_FORCE_BREW_WRAPPER:               {
 | 
			
		||||
        description: "If set, require `$HOMEBREW_BREW_WRAPPER` to be set to the same value as " \
 | 
			
		||||
        description: "If set, require `brew` to be invoked by the value of " \
 | 
			
		||||
                     "`$HOMEBREW_FORCE_BREW_WRAPPER` for non-trivial `brew` commands.",
 | 
			
		||||
      },
 | 
			
		||||
      HOMEBREW_FORCE_VENDOR_RUBY:                {
 | 
			
		||||
@ -393,10 +390,6 @@ module Homebrew
 | 
			
		||||
        description: "If set, do not print any hints about changing Homebrew's behaviour with environment variables.",
 | 
			
		||||
        boolean:     true,
 | 
			
		||||
      },
 | 
			
		||||
      HOMEBREW_NO_FORCE_BREW_WRAPPER:            {
 | 
			
		||||
        description: "If set, disables `$HOMEBREW_FORCE_BREW_WRAPPER` behaviour, even if set.",
 | 
			
		||||
        boolean:     true,
 | 
			
		||||
      },
 | 
			
		||||
      HOMEBREW_NO_GITHUB_API:                    {
 | 
			
		||||
        description: "If set, do not use the GitHub API, e.g. for searches or fetching relevant issues " \
 | 
			
		||||
                     "after a failed install.",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										23
									
								
								Library/Homebrew/utils/pid_path.rb
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										23
									
								
								Library/Homebrew/utils/pid_path.rb
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
#!/usr/bin/env ruby
 | 
			
		||||
# typed: strict
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "fiddle"
 | 
			
		||||
 | 
			
		||||
libproc = Fiddle.dlopen("/usr/lib/libproc.dylib")
 | 
			
		||||
 | 
			
		||||
proc_pidpath = Fiddle::Function.new(
 | 
			
		||||
  libproc["proc_pidpath"],
 | 
			
		||||
  [Fiddle::TYPE_INT, Fiddle::TYPE_VOIDP, Fiddle::TYPE_UINT32_T],
 | 
			
		||||
  Fiddle::TYPE_INT,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
pid = ARGV[0]&.to_i
 | 
			
		||||
exit 1 unless pid
 | 
			
		||||
 | 
			
		||||
bufsize = 4 * 1024 # PROC_PIDPATHINFO_MAXSIZE = 4 * MAXPATHLEN
 | 
			
		||||
buf = "\0" * bufsize
 | 
			
		||||
ptr = Fiddle::Pointer.to_ptr(buf)
 | 
			
		||||
 | 
			
		||||
ret = proc_pidpath.call(pid, ptr, bufsize)
 | 
			
		||||
puts ptr.to_s.strip if ret.positive?
 | 
			
		||||
							
								
								
									
										14
									
								
								bin/brew
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								bin/brew
									
									
									
									
									
								
							@ -100,13 +100,6 @@ unset BREW_FILE_DIRECTORY
 | 
			
		||||
# keg_relocate.rb, formula_cellar_checks.rb, and test/global_spec.rb need to change.
 | 
			
		||||
HOMEBREW_LIBRARY="${HOMEBREW_REPOSITORY}/Library"
 | 
			
		||||
 | 
			
		||||
# Use HOMEBREW_BREW_WRAPPER if set.
 | 
			
		||||
export HOMEBREW_ORIGINAL_BREW_FILE="${HOMEBREW_BREW_FILE}"
 | 
			
		||||
if [[ -n "${HOMEBREW_BREW_WRAPPER:-}" ]]
 | 
			
		||||
then
 | 
			
		||||
  HOMEBREW_BREW_FILE="${HOMEBREW_BREW_WRAPPER}"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# These variables are exported in this file and are not allowed to be overridden by the user.
 | 
			
		||||
BIN_BREW_EXPORTED_VARS=(
 | 
			
		||||
  HOMEBREW_BREW_FILE
 | 
			
		||||
@ -168,6 +161,13 @@ then
 | 
			
		||||
  export_homebrew_env_file "/etc/homebrew/brew.env"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Use HOMEBREW_FORCE_BREW_WRAPPER if set.
 | 
			
		||||
export HOMEBREW_ORIGINAL_BREW_FILE="${HOMEBREW_BREW_FILE}"
 | 
			
		||||
if [[ -n "${HOMEBREW_FORCE_BREW_WRAPPER:-}" ]]
 | 
			
		||||
then
 | 
			
		||||
  HOMEBREW_BREW_FILE="${HOMEBREW_FORCE_BREW_WRAPPER}"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Copy and export all HOMEBREW_* variables previously mentioned in
 | 
			
		||||
# manpage or used elsewhere by Homebrew.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user