summaryrefslogtreecommitdiff
path: root/symbol_inject/macho.go
diff options
context:
space:
mode:
author Yabin Cui <yabinc@google.com> 2022-10-27 09:56:20 -0700
committer Yabin Cui <yabinc@google.com> 2022-11-02 14:32:53 -0700
commite79fe01c593b3734e70f4361efdd3357bb31b39a (patch)
tree4100815b8f5d89353d3fc4df1f98089628d96019 /symbol_inject/macho.go
parente127b4d060ed0e238ac68923a7eb77b04fd6272b (diff)
symbol_inject: add linkerSigned flag in codesign of Mach-O binaries.
With linkerSigned flag, codesign will still be valid after stripping. Bug: 251222821 Test: build aapt2 and both non-stripped and stripped version work. Change-Id: Ic3a2b9fcaf30eb306fed7db6568f6699cc640cde
Diffstat (limited to 'symbol_inject/macho.go')
-rw-r--r--symbol_inject/macho.go81
1 files changed, 79 insertions, 2 deletions
diff --git a/symbol_inject/macho.go b/symbol_inject/macho.go
index 9946d34af..ca3d50e9c 100644
--- a/symbol_inject/macho.go
+++ b/symbol_inject/macho.go
@@ -16,9 +16,12 @@ package symbol_inject
import (
"debug/macho"
+ "encoding/binary"
"fmt"
"io"
+ "os"
"os/exec"
+ "path/filepath"
"sort"
"strings"
)
@@ -98,6 +101,80 @@ func dumpMachoSymbols(r io.ReaderAt) error {
}
func CodeSignMachoFile(path string) error {
- cmd := exec.Command("/usr/bin/codesign", "--force", "-s", "-", path)
- return cmd.Run()
+ filename := filepath.Base(path)
+ cmd := exec.Command("/usr/bin/codesign", "--force", "-s", "-", "-i", filename, path)
+ if err := cmd.Run(); err != nil {
+ return err
+ }
+ return modifyCodeSignFlags(path)
+}
+
+const LC_CODE_SIGNATURE = 0x1d
+const CSSLOT_CODEDIRECTORY = 0
+
+// To make codesign not invalidated by stripping, modify codesign flags to 0x20002
+// (adhoc | linkerSigned).
+func modifyCodeSignFlags(path string) error {
+ f, err := os.OpenFile(path, os.O_RDWR, 0)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ // Step 1: find code signature section.
+ machoFile, err := macho.NewFile(f)
+ if err != nil {
+ return err
+ }
+ var codeSignSectionOffset uint32 = 0
+ var codeSignSectionSize uint32 = 0
+ for _, l := range machoFile.Loads {
+ data := l.Raw()
+ cmd := machoFile.ByteOrder.Uint32(data)
+ if cmd == LC_CODE_SIGNATURE {
+ codeSignSectionOffset = machoFile.ByteOrder.Uint32(data[8:])
+ codeSignSectionSize = machoFile.ByteOrder.Uint32(data[12:])
+ }
+ }
+ if codeSignSectionOffset == 0 {
+ return fmt.Errorf("code signature section not found")
+ }
+
+ data := make([]byte, codeSignSectionSize)
+ _, err = f.ReadAt(data, int64(codeSignSectionOffset))
+ if err != nil {
+ return err
+ }
+
+ // Step 2: get flags offset.
+ blobCount := binary.BigEndian.Uint32(data[8:])
+ off := 12
+ var codeDirectoryOff uint32 = 0
+ for blobCount > 0 {
+ blobType := binary.BigEndian.Uint32(data[off:])
+ if blobType == CSSLOT_CODEDIRECTORY {
+ codeDirectoryOff = binary.BigEndian.Uint32(data[off+4:])
+ break
+ }
+ blobCount--
+ off += 8
+ }
+ if codeDirectoryOff == 0 {
+ return fmt.Errorf("no code directory in code signature section")
+ }
+ flagsOff := codeSignSectionOffset + codeDirectoryOff + 12
+
+ // Step 3: modify flags.
+ flagsData := make([]byte, 4)
+ _, err = f.ReadAt(flagsData, int64(flagsOff))
+ if err != nil {
+ return err
+ }
+ oldFlags := binary.BigEndian.Uint32(flagsData)
+ if oldFlags != 0x2 {
+ return fmt.Errorf("unexpected flags in code signature section: 0x%x", oldFlags)
+ }
+ binary.BigEndian.PutUint32(flagsData, 0x20002)
+ _, err = f.WriteAt(flagsData, int64(flagsOff))
+ return err
}