forked from lima-vm/lima
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request lima-vm#1743 from AkihiroSuda/sign-qemu-binary
qemu: ask to sign QEMU binary when the binary is not properly signed
- Loading branch information
Showing
3 changed files
with
113 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// Package entitlementutil provides a workaround for https://github.com/lima-vm/lima/issues/1742 | ||
package entitlementutil | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"strings" | ||
|
||
"github.com/AlecAivazis/survey/v2" | ||
"github.com/mattn/go-isatty" | ||
"github.com/sirupsen/logrus" | ||
) | ||
|
||
// IsSigned returns an error if the binary is not signed, or the sign is invalid, | ||
// or not associated with the "com.apple.security.hypervisor" entitlement. | ||
func IsSigned(qExe string) error { | ||
cmd := exec.Command("codesign", "--verify", qExe) | ||
out, err := cmd.CombinedOutput() | ||
logrus.WithError(err).Debugf("Executed %v: out=%q", cmd.Args, string(out)) | ||
if err != nil { | ||
return fmt.Errorf("failed to run %v: %w (out=%q)", cmd.Args, err, string(out)) | ||
} | ||
|
||
cmd = exec.Command("codesign", "--display", "--entitlements", "-", "--xml", qExe) | ||
out, err = cmd.CombinedOutput() | ||
logrus.WithError(err).Debugf("Executed %v: out=%q", cmd.Args, string(out)) | ||
if err != nil { | ||
return fmt.Errorf("failed to run %v: %w (out=%q)", cmd.Args, err, string(out)) | ||
} | ||
if !strings.Contains(string(out), "com.apple.security.hypervisor") { | ||
return fmt.Errorf("binary %q seems signed but lacking the \"com.apple.security.hypervisor\" entitlement", qExe) | ||
} | ||
return nil | ||
} | ||
|
||
func Sign(qExe string) error { | ||
ent, err := os.CreateTemp("", "lima-qemu-entitlements-*.xml") | ||
if err != nil { | ||
return fmt.Errorf("failed to create a temporary file for signing QEMU binary: %w", err) | ||
} | ||
entName := ent.Name() | ||
defer os.RemoveAll(entName) | ||
const entXML = `<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>com.apple.security.hypervisor</key> | ||
<true/> | ||
</dict> | ||
</plist>` | ||
if _, err = ent.Write([]byte(entXML)); err != nil { | ||
return fmt.Errorf("Failed to write to a temporary file %q for signing QEMU binary: %w", entName, err) | ||
} | ||
ent.Close() | ||
signCmd := exec.Command("codesign", "--sign", "-", "--entitlements", entName, "--force", qExe) | ||
out, err := signCmd.CombinedOutput() | ||
logrus.WithError(err).Debugf("Executed %v: out=%q", signCmd.Args, string(out)) | ||
if err != nil { | ||
return fmt.Errorf("failed to run %v: %w (out=%q)", signCmd.Args, err, string(out)) | ||
} | ||
return nil | ||
} | ||
|
||
// AskToSignIfNotSignedProperly asks to sign the QEMU binary with the "com.apple.security.hypervisor" entitlement. | ||
// | ||
// On Homebrew, QEMU binaries are usually already signed, but Homebrew's signing infrastructure is broken for Intel as of Augest 2023. | ||
// https://github.com/lima-vm/lima/issues/1742 | ||
func AskToSignIfNotSignedProperly(qExe string) { | ||
if isSignedErr := IsSigned(qExe); isSignedErr != nil { | ||
logrus.WithError(isSignedErr).Warnf("QEMU binary %q is not properly signed with the \"com.apple.security.hypervisor\" entitlement", qExe) | ||
var ans bool | ||
if isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd()) { | ||
prompt := &survey.Confirm{ | ||
Message: fmt.Sprintf("Try to sign %q with the \"com.apple.security.hypervisor\" entitlement?", qExe), | ||
Default: true, | ||
} | ||
if askErr := survey.AskOne(prompt, &ans); askErr != nil { | ||
logrus.WithError(askErr).Warn("No answer was given") | ||
} | ||
} | ||
if ans { | ||
if signErr := Sign(qExe); signErr != nil { | ||
logrus.WithError(signErr).Warnf("Failed to sign %q", qExe) | ||
} else { | ||
logrus.Infof("Successfully signed %q with the \"com.apple.security.hypervisor\" entitlement", qExe) | ||
} | ||
} else { | ||
logrus.Warn("You have to sign the QEMU binary with the \"com.apple.security.hypervisor\" entitlement manually. See https://github.com/lima-vm/lima/issues/1742 .") | ||
} | ||
} else { | ||
logrus.Infof("QEMU binary %q seems properly signed with the \"com.apple.security.hypervisor\" entitlement", qExe) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters