Merge pull request #24325 from Homebrew/keg-codesign-temporary-copy

Sign temporary keg copies before restoring them
This commit is contained in:
Mike McQuaid authored and GitHub committed 2026-10-22 12:02:59 +00:00
commit 17a9eaaf09
2 files changed
+48 -11

No files matched your search

+13 -11
View File
@@ -120,20 +120,22 @@ module OS
"--preserve-metadata=entitlements,requirements,flags,runtime",
file)
# If the codesigning fails, it may be a bug in Apple's codesign utility.
# A known workaround is to copy the file to another inode, then move it back
# erasing the previous file. Then sign again.
# If codesigning fails, retry on a new inode at a different path.
# Sign before moving it back, as macOS may restore com.apple.provenance
# at the original path.
Dir::Tmpname.create("workaround") do |tmppath|
FileUtils.cp file, tmppath
FileUtils.mv tmppath, file, force: true
end
odebug "Codesigning (2nd try) #{file}"
result = system_command("codesign", args: [
"--sign", "-", "--force",
"--preserve-metadata=entitlements,requirements,flags,runtime",
file
], print_stderr: false)
odebug "Codesigning (2nd try) #{file}"
result = system_command("codesign", args: [
"--sign", "-", "--force",
"--preserve-metadata=entitlements,requirements,flags,runtime",
tmppath
], print_stderr: false)
FileUtils.mv tmppath, file if result.success?
ensure
FileUtils.rm_f tmppath
end
return if result.success?
onoe <<~EOS
+35
View File
@@ -96,6 +96,41 @@ RSpec.describe Keg do
keg.codesign_patched_binary(file)
end
it "signs a temporary copy when the original path rejects signing on Intel" do
Pathname(file).dirname.mkpath
File.write(file, "unsigned")
allow(Hardware::CPU).to receive(:arm?).and_return(false)
allow(SystemCommand).to receive(:quiet_system).and_return(false)
allow(keg).to receive(:system_command) do |_, args:, **|
if args.first == "--verify"
instance_double(SystemCommand::Result, stderr: "#{file}: invalid signature")
elsif args.last == file
instance_double(SystemCommand::Result, success?: false, stderr: "#{file}: detritus not allowed")
else
File.write(args.last, "signed")
instance_double(SystemCommand::Result, success?: true)
end
end
keg.codesign_patched_binary(file)
expect(File.read(file)).to eq("signed")
end
it "raises when replacing the binary after a successful signing retry fails on Intel" do
Pathname(file).dirname.mkpath
touch file
allow(Hardware::CPU).to receive(:arm?).and_return(false)
allow(SystemCommand).to receive(:quiet_system).and_return(false)
allow(keg).to receive(:system_command).and_return(
instance_double(SystemCommand::Result, stderr: "#{file}: invalid signature"),
instance_double(SystemCommand::Result, success?: true),
)
allow(File).to receive(:rename).with(anything, file).and_raise(Errno::EACCES)
expect { keg.codesign_patched_binary(file) }.to raise_error(Errno::EACCES)
end
end
describe "#relocate_dynamic_linkage" do