From ccdf39ff4ea0e5ece9f2722e2576bfdcf32c521b Mon Sep 17 00:00:00 2001 From: Bo Anderson Date: Tue, 10 Dec 2024 05:24:10 +0000 Subject: [PATCH] dev-cmd/tap-new: improve handling of multi-user setups --- Library/Homebrew/dev-cmd/tap-new.rb | 25 +++++++++++++++++++++---- Library/Homebrew/utils/github/api.rb | 13 ++----------- Library/Homebrew/utils/uid.rb | 9 +++++++++ 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/Library/Homebrew/dev-cmd/tap-new.rb b/Library/Homebrew/dev-cmd/tap-new.rb index 6e59498428..5f1423fb64 100644 --- a/Library/Homebrew/dev-cmd/tap-new.rb +++ b/Library/Homebrew/dev-cmd/tap-new.rb @@ -4,6 +4,7 @@ require "abstract_command" require "fileutils" require "tap" +require "utils/uid" module Homebrew module DevCmd @@ -172,16 +173,32 @@ module Homebrew write_path(tap, ".github/workflows/publish.yml", actions_publish) unless args.no_git? - cd tap.path do + cd tap.path do |path| Utils::Git.set_name_email! Utils::Git.setup_gpg! # Would be nice to use --initial-branch here but it's not available in # older versions of Git that we support. safe_system "git", "-c", "init.defaultBranch=#{branch}", "init" - safe_system "git", "add", "--all" - safe_system "git", "commit", "-m", "Create #{tap} tap" - safe_system "git", "branch", "-m", branch + + args = [] + git_owner = File.stat(File.join(path, ".git")).uid + if git_owner != Process.uid && git_owner == Process.euid + # Under Homebrew user model, EUID is permitted to execute commands under the UID. + # Root users are never allowed (see brew.sh). + args << "-c" << "safe.directory=#{path}" + end + + # Use the configuration of the original user, which will have author information and signing keys. + Utils::UID.drop_euid do + env = { HOME: Utils::UID.uid_home }.compact + env[:TMPDIR] = nil if (tmpdir = ENV.fetch("TMPDIR", nil)) && !File.writable?(tmpdir) + with_env(env) do + safe_system "git", *args, "add", "--all" + safe_system "git", *args, "commit", "-m", "Create #{tap} tap" + safe_system "git", *args, "branch", "-m", branch + end + end end end diff --git a/Library/Homebrew/utils/github/api.rb b/Library/Homebrew/utils/github/api.rb index bcc2bcbe3b..26b4e3d0aa 100644 --- a/Library/Homebrew/utils/github/api.rb +++ b/Library/Homebrew/utils/github/api.rb @@ -135,15 +135,6 @@ module GitHub JSON::ParserError, ].freeze - sig { returns(T.nilable(String)) } - private_class_method def self.uid_home - require "etc" - Etc.getpwuid(Process.uid)&.dir - rescue ArgumentError - # Cover for misconfigured NSS setups - nil - end - # Gets the token from the GitHub CLI for github.com. sig { returns(T.nilable(String)) } def self.github_cli_token @@ -152,7 +143,7 @@ module GitHub # Avoid `Formula["gh"].opt_bin` so this method works even with `HOMEBREW_DISABLE_LOAD_FORMULA`. env = { "PATH" => PATH.new(HOMEBREW_PREFIX/"opt/gh/bin", ENV.fetch("PATH")), - "HOME" => uid_home, + "HOME" => Utils::UID.uid_home, }.compact gh_out, _, result = system_command "gh", args: ["auth", "token", "--hostname", "github.com"], @@ -173,7 +164,7 @@ module GitHub git_credential_out, _, result = system_command "git", args: ["credential-osxkeychain", "get"], input: ["protocol=https\n", "host=github.com\n"], - env: { "HOME" => uid_home }.compact, + env: { "HOME" => Utils::UID.uid_home }.compact, print_stderr: false return unless result.success? diff --git a/Library/Homebrew/utils/uid.rb b/Library/Homebrew/utils/uid.rb index 4c102a2b8a..129c569bb8 100644 --- a/Library/Homebrew/utils/uid.rb +++ b/Library/Homebrew/utils/uid.rb @@ -15,5 +15,14 @@ module Utils Process::Sys.seteuid(original_euid) end end + + sig { returns(T.nilable(String)) } + def self.uid_home + require "etc" + Etc.getpwuid(Process.uid)&.dir + rescue ArgumentError + # Cover for misconfigured NSS setups + nil + end end end