Skip to content

Commit

Permalink
qemu: automatically sign QEMU binary when the binary is not properly …
Browse files Browse the repository at this point in the history
…signed

Workaround for issue 1742 .
This workaround is needed because Homebrew's QEMU binary is not properly signed since v8.0.4.

Signed-off-by: Akihiro Suda <[email protected]>
  • Loading branch information
AkihiroSuda committed Aug 13, 2023
1 parent 495271c commit a433811
Showing 1 changed file with 63 additions and 0 deletions.
63 changes: 63 additions & 0 deletions pkg/qemu/qemu_driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,65 @@ func (l *LimaQemuDriver) CreateDisk() error {
return EnsureDisk(qCfg)
}

// isHVF returns true if qArgs enables HVF.
// isHVF is over-approximated.
func isHVF(qArgs []string) bool {
if runtime.GOOS != "darwin" {
return false
}
for _, s := range qArgs {
// over-approximation
if strings.Contains(s, "hvf") {
return true
}
}
return false
}

// reSignQEMUBinary re-signs QEMU binary with `codesign`,
// as a workaround for https://github.com/lima-vm/lima/issues/1742
//
// This workaround is needed for Homebrew environments on Intel
// because Homebrew's signing infrastructure is broken for Intel as of Augest 2023.
func reSignQEMUBinary(qExe string) {
verifyCmd := exec.Command("codesign", "--verify", qExe)
out, err := verifyCmd.CombinedOutput()
logrus.WithError(err).Debugf("Executed %v: out=%q", verifyCmd.Args, string(out))
if err == nil {
logrus.Debugf("QEMU binary %q seems already signed", qExe)
return
}

ent, err := os.CreateTemp("", "lima-qemu-entitlements-*.xml")
if err != nil {
logrus.WithError(err).Error("Failed to create a temporary file for signing QEMU binary")
return
}
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 {
logrus.WithError(err).Errorf("Failed to write to a temporary file %q for signing QEMU binary", entName)
return
}
ent.Close()
signCmd := exec.Command("codesign", "--sign", "-", "--entitlements", entName, "--force", qExe)
logrus.Debugf("QEMU binary %q does not seem signed. Will attempt to sign: %v", qExe, signCmd.Args)
out, err = signCmd.CombinedOutput()
logrus.WithError(err).Debugf("Executed %v: out=%q", signCmd.Args, string(out))
if err != nil {
logrus.WithError(err).Warnf("Failed to sign QEMU binary %q: %v: out=%q", qExe,
signCmd.Args, string(out))
}
}

func (l *LimaQemuDriver) Start(ctx context.Context) (chan error, error) {
ctx, cancel := context.WithCancel(ctx)
defer func() {
Expand All @@ -78,6 +137,10 @@ func (l *LimaQemuDriver) Start(ctx context.Context) (chan error, error) {
return nil, err
}

if isHVF(qArgs) {
reSignQEMUBinary(qExe)
}

var vhostCmds []*exec.Cmd
if *l.Yaml.MountType == limayaml.VIRTIOFS {
vhostExe, err := FindVirtiofsd(qExe)
Expand Down

0 comments on commit a433811

Please sign in to comment.