Skip to content

Commit

Permalink
CodeSign: pad LINKEDIT to multiple of page size when reading (#66)
Browse files Browse the repository at this point in the history
When we are creating a new CodeSignature, we align its offset up to a multiple
of the page size; we then read the existing LINKEDIT section (and the entire
beginning of the file, for signing) based on the location of that code
signature. If the existing LINKEDIT section's end was not page-aligned, we get
an EOF when attempting to read up to the page-aligned flie size, causing
signing to fail.

This change limits our read to the actual size of the file (or LINKEDIT
section, at least), while keeping the buffer we read into the correct
size (and therefore implicitly padding it with zeroes, which will get written
out when we rewrite the LINKEDIT section and new signature).
  • Loading branch information
jkt-signal authored Sep 27, 2024
1 parent c4f8bca commit 6e27af0
Showing 1 changed file with 10 additions and 5 deletions.
15 changes: 10 additions & 5 deletions export.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,10 +324,15 @@ func (f *File) CodeSign(config *codesign.Config) error {

config.CodeSize = uint64(cs.Offset)

// cache __LINKEDIT data (up to but not including any existing code signature) for saving later
// cache __LINKEDIT data (up to but not including any existing code signature) for saving later.
// if the actual data doesn't go up to a page boundary (because we're adding a new signature), pad it with zeroes
ledata := make([]byte, uint64(cs.Offset)-linkedit.Offset)
if _, err := f.cr.ReadAtAddr(ledata, linkedit.Addr); err != nil {
return fmt.Errorf("failed to read __LINKEDIT data: %v", err)
size := uint64(len(ledata))
if size > linkedit.Filesz {
size = linkedit.Filesz
}
if n, err := f.cr.ReadAtAddr(ledata[:size], linkedit.Addr); err != nil {
return fmt.Errorf("failed to read __LINKEDIT data: %d, %v", n, err)
}
f.ledata = bytes.NewBuffer(ledata)

Expand All @@ -337,9 +342,9 @@ func (f *File) CodeSign(config *codesign.Config) error {
// update LC_CODE_SIGNATURE size
cs.Size = uint32((linkedit.Offset + linkedit.Filesz) - uint64(cs.Offset))

// read data to be signed
// read data to be signed; pad to beginning of code signature if necessary (in case we added a signature to a not-page-aligned-size file)
data := make([]byte, cs.Offset)
if _, err := f.ReadAt(data, 0); err != nil {
if _, err := f.ReadAt(data[:linkedit.Offset+size], 0); err != nil {
return fmt.Errorf("failed to read codesign data: %v", err)
}
// write modified file header and load commands (including __LINKEDIT and CodeSignature), since they are covered by hashes
Expand Down

0 comments on commit 6e27af0

Please sign in to comment.