From 09b072b90823110019a0fe0e64d244a178653fff Mon Sep 17 00:00:00 2001 From: John Reiser Date: Fri, 3 Aug 2012 13:28:33 -0700 Subject: [PATCH] Leave space for code signing on Mac OS X. --- NEWS | 2 + src/p_mach.cpp | 202 +++++++++++++++++++++++++++++++------------------ 2 files changed, 129 insertions(+), 75 deletions(-) diff --git a/NEWS b/NEWS index 462a29cd..651b3258 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ User visible changes for UPX ================================================================== Changes in 3.09 (XX XXX XXXX): + * Allow for code signing on Mac OS X executables. + * bug fixes Changes in 3.08 (12 Dec 2011): * Fix allocation in runtime stub for darwin.macho-entry (i386 and amd64). diff --git a/src/p_mach.cpp b/src/p_mach.cpp index 0e82c166..11636cb7 100644 --- a/src/p_mach.cpp +++ b/src/p_mach.cpp @@ -351,7 +351,7 @@ PackMachBase::buildMachLoader( int const GAP = 128; // must match stub/l_mac_ppc.S int const NO_LAP = 64; // must match stub/src/*darwin*.S - segcmdo.vmsize += h.sz_unc - h.sz_cpr + GAP + NO_LAP; + segcmdo[0].vmsize += h.sz_unc - h.sz_cpr + GAP + NO_LAP; addStubEntrySections(ft); @@ -463,62 +463,6 @@ PackMachBase::compare_segment_command(void const *const aa, void const *const return 0; } -void PackMachPPC32::pack4(OutputFile *fo, Filter &ft) // append PackHeader -{ - // offset of p_info in compressed file - overlay_offset = sizeof(mhdro) + sizeof(segcmdo) + sizeof(threado) + sizeof(linfo); - - super::pack4(fo, ft); - segcmdo.filesize = fo->getBytesWritten(); - segcmdo.vmsize += segcmdo.filesize; - fo->seek(sizeof(mhdro), SEEK_SET); - fo->rewrite(&segcmdo, sizeof(segcmdo)); - fo->rewrite(&threado, sizeof(threado)); - fo->rewrite(&linfo, sizeof(linfo)); -} - -void PackMachI386::pack4(OutputFile *fo, Filter &ft) // append PackHeader -{ - // offset of p_info in compressed file - overlay_offset = sizeof(mhdro) + sizeof(segcmdo) + sizeof(threado) + sizeof(linfo); - - super::pack4(fo, ft); - segcmdo.filesize = fo->getBytesWritten(); - segcmdo.vmsize += segcmdo.filesize; - fo->seek(sizeof(mhdro), SEEK_SET); - fo->rewrite(&segcmdo, sizeof(segcmdo)); - fo->rewrite(&threado, sizeof(threado)); - fo->rewrite(&linfo, sizeof(linfo)); -} - -void PackMachAMD64::pack4(OutputFile *fo, Filter &ft) // append PackHeader -{ - // offset of p_info in compressed file - overlay_offset = sizeof(mhdro) + sizeof(segcmdo) + sizeof(threado) + sizeof(linfo); - - super::pack4(fo, ft); - segcmdo.filesize = fo->getBytesWritten(); - segcmdo.vmsize += segcmdo.filesize; - fo->seek(sizeof(mhdro), SEEK_SET); - fo->rewrite(&segcmdo, sizeof(segcmdo)); - fo->rewrite(&threado, sizeof(threado)); - fo->rewrite(&linfo, sizeof(linfo)); -} - -void PackMachARMEL::pack4(OutputFile *fo, Filter &ft) // append PackHeader -{ - // offset of p_info in compressed file - overlay_offset = sizeof(mhdro) + sizeof(segcmdo) + sizeof(threado) + sizeof(linfo); - - super::pack4(fo, ft); - segcmdo.filesize = fo->getBytesWritten(); - segcmdo.vmsize += segcmdo.filesize; - fo->seek(sizeof(mhdro), SEEK_SET); - fo->rewrite(&segcmdo, sizeof(segcmdo)); - fo->rewrite(&threado, sizeof(threado)); - fo->rewrite(&linfo, sizeof(linfo)); -} - #undef PAGE_MASK #undef PAGE_SIZE #define PAGE_MASK (~0u<<12) @@ -529,6 +473,102 @@ void PackMachARMEL::pack4(OutputFile *fo, Filter &ft) // append PackHeader #define PAGE_MASK64 (~(acc_uint64l_t)0<<12) #define PAGE_SIZE64 -PAGE_MASK64 +void PackMachPPC32::pack4(OutputFile *fo, Filter &ft) // append PackHeader +{ + // offset of p_info in compressed file + overlay_offset = sizeof(mhdro) + sizeof(segcmdo) + sizeof(threado) + sizeof(linfo); + if (my_filetype==Mach_header::MH_EXECUTE) { + overlay_offset += sizeof(linkedito); + } + + super::pack4(fo, ft); + segcmdo[0].filesize = fo->getBytesWritten(); + segcmdo[0].vmsize += segcmdo[0].filesize; + unsigned const foff1 = (PAGE_MASK & (~PAGE_MASK + segcmdo[0].filesize)); + segcmdo[1].fileoff = foff1; + segcmdo[1].vmaddr = segcmdo[0].vmaddr + foff1; + fo->seek(foff1 - 1, SEEK_SET); fo->write("", 1); + fo->seek(sizeof(mhdro), SEEK_SET); + fo->rewrite(&segcmdo, sizeof(segcmdo)); + fo->rewrite(&threado, sizeof(threado)); + if (my_filetype==Mach_header::MH_EXECUTE) { + fo->rewrite(&linkedito, sizeof(linkedito)); + } + fo->rewrite(&linfo, sizeof(linfo)); +} + +void PackMachI386::pack4(OutputFile *fo, Filter &ft) // append PackHeader +{ + // offset of p_info in compressed file + overlay_offset = sizeof(mhdro) + sizeof(segcmdo) + sizeof(threado) + sizeof(linfo); + if (my_filetype==Mach_header::MH_EXECUTE) { + overlay_offset += sizeof(linkedito); + } + + super::pack4(fo, ft); + segcmdo[0].filesize = fo->getBytesWritten(); + segcmdo[0].vmsize += segcmdo[0].filesize; + unsigned const foff1 = (PAGE_MASK & (~PAGE_MASK + segcmdo[0].filesize)); + segcmdo[1].fileoff = foff1; + segcmdo[1].vmaddr = segcmdo[0].vmaddr + foff1; + fo->seek(foff1 - 1, SEEK_SET); fo->write("", 1); + fo->seek(sizeof(mhdro), SEEK_SET); + fo->rewrite(&segcmdo, sizeof(segcmdo)); + fo->rewrite(&threado, sizeof(threado)); + if (my_filetype==Mach_header::MH_EXECUTE) { + fo->rewrite(&linkedito, sizeof(linkedito)); + } + fo->rewrite(&linfo, sizeof(linfo)); +} + +void PackMachAMD64::pack4(OutputFile *fo, Filter &ft) // append PackHeader +{ + // offset of p_info in compressed file + overlay_offset = sizeof(mhdro) + sizeof(segcmdo) + sizeof(threado) + sizeof(linfo); + if (my_filetype==Mach_header::MH_EXECUTE) { + overlay_offset += sizeof(linkedito); + } + + super::pack4(fo, ft); + segcmdo[0].filesize = fo->getBytesWritten(); + segcmdo[0].vmsize += segcmdo[0].filesize; + unsigned const foff1 = (PAGE_MASK64 & (~PAGE_MASK64 + segcmdo[0].filesize)); + segcmdo[1].fileoff = foff1; + segcmdo[1].vmaddr = segcmdo[0].vmaddr + foff1; + fo->seek(foff1 - 1, SEEK_SET); fo->write("", 1); + fo->seek(sizeof(mhdro), SEEK_SET); + fo->rewrite(&segcmdo, sizeof(segcmdo)); + fo->rewrite(&threado, sizeof(threado)); + if (my_filetype==Mach_header::MH_EXECUTE) { + fo->rewrite(&linkedito, sizeof(linkedito)); + } + fo->rewrite(&linfo, sizeof(linfo)); +} + +void PackMachARMEL::pack4(OutputFile *fo, Filter &ft) // append PackHeader +{ + // offset of p_info in compressed file + overlay_offset = sizeof(mhdro) + sizeof(segcmdo) + sizeof(threado) + sizeof(linfo); + if (my_filetype==Mach_header::MH_EXECUTE) { + overlay_offset += sizeof(linkedito); + } + + super::pack4(fo, ft); + segcmdo[0].filesize = fo->getBytesWritten(); + segcmdo[0].vmsize += segcmdo[0].filesize; + unsigned const foff1 = (PAGE_MASK & (~PAGE_MASK + segcmdo[0].filesize)); + segcmdo[1].fileoff = foff1; + segcmdo[1].vmaddr = segcmdo[0].vmaddr + foff1; + fo->seek(foff1 - 1, SEEK_SET); fo->write("", 1); + fo->seek(sizeof(mhdro), SEEK_SET); + fo->rewrite(&segcmdo, sizeof(segcmdo)); + fo->rewrite(&threado, sizeof(threado)); + if (my_filetype==Mach_header::MH_EXECUTE) { + fo->rewrite(&linkedito, sizeof(linkedito)); + } + fo->rewrite(&linfo, sizeof(linfo)); +} + template void PackMachBase::pack4dylib( // append PackHeader OutputFile *const fo, @@ -737,7 +777,7 @@ void PackMachPPC32::pack3(OutputFile *fo, Filter &ft) // append loader disp = 4+ len - sz_mach_headers; // 4: sizeof(instruction) fo->write(&disp, sizeof(disp)); - threado.state.srr0 = len + segcmdo.vmaddr; /* entry address */ + threado.state.srr0 = len + segcmdo[0].vmaddr; /* entry address */ super::pack3(fo, ft); } @@ -751,7 +791,7 @@ void PackMachI386::pack3(OutputFile *fo, Filter &ft) // append loader disp = len - sz_mach_headers; fo->write(&disp, sizeof(disp)); - threado.state.eip = len + sizeof(disp) + segcmdo.vmaddr; /* entry address */ + threado.state.eip = len + sizeof(disp) + segcmdo[0].vmaddr; /* entry address */ super::pack3(fo, ft); } @@ -765,7 +805,7 @@ void PackMachAMD64::pack3(OutputFile *fo, Filter &ft) // append loader disp = len - sz_mach_headers; fo->write(&disp, sizeof(disp)); - threado.state.rip = len + sizeof(disp) + segcmdo.vmaddr; /* entry address */ + threado.state.rip = len + sizeof(disp) + segcmdo[0].vmaddr; /* entry address */ super::pack3(fo, ft); } @@ -779,7 +819,7 @@ void PackMachARMEL::pack3(OutputFile *fo, Filter &ft) // append loader disp = len - sz_mach_headers; fo->write(&disp, sizeof(disp)); - threado.state.pc = len + sizeof(disp) + segcmdo.vmaddr; /* entry address */ + threado.state.pc = len + sizeof(disp) + segcmdo[0].vmaddr; /* entry address */ super::pack3(fo, ft); } @@ -987,7 +1027,7 @@ int PackMachBase::pack2(OutputFile *fo, Filter &ft) // append compressed bo if (my_filetype!=Mach_header::MH_DYLIB) if ((off_t)total_in != file_size) throwEOFException(); - segcmdo.filesize = fo->getBytesWritten(); + segcmdo[0].filesize = fo->getBytesWritten(); return 1; } @@ -1038,34 +1078,42 @@ void PackMachBase::pack1(OutputFile *const fo, Filter &/*ft*/) // generate e unsigned const lc_seg = lc_segment[sizeof(Addr)>>3]; mhdro = mhdri; if (my_filetype==Mach_header::MH_EXECUTE) { - mhdro.ncmds = 2; + mhdro.ncmds = 3; mhdro.sizeofcmds = sizeof(segcmdo) + my_thread_command_size; mhdro.flags = Mach_header::MH_NOUNDEFS; } fo->write(&mhdro, sizeof(mhdro)); - segcmdo.cmd = lc_seg; - segcmdo.cmdsize = sizeof(segcmdo); - strncpy((char *)segcmdo.segname, "__TEXT", sizeof(segcmdo.segname)); + segcmdo[0].cmd = lc_seg; + segcmdo[0].cmdsize = sizeof(segcmdo[0]); + strncpy((char *)segcmdo[0].segname, "__TEXT", sizeof(segcmdo[0].segname)); if (my_filetype==Mach_header::MH_EXECUTE) { - segcmdo.vmaddr = PAGE_MASK64 & (~PAGE_MASK64 + + segcmdo[0].vmaddr = PAGE_MASK64 & (~PAGE_MASK64 + msegcmd[n_segment -1].vmsize + msegcmd[n_segment -1].vmaddr ); } if (my_filetype==Mach_header::MH_DYLIB) { - segcmdo.vmaddr = 0; + segcmdo[0].vmaddr = 0; } - segcmdo.vmsize = 0; // adjust later - segcmdo.fileoff = 0; - segcmdo.filesize = 0; // adjust later - segcmdo.initprot = segcmdo.maxprot = + segcmdo[0].vmsize = 0; // adjust later + segcmdo[0].fileoff = 0; + segcmdo[0].filesize = 0; // adjust later + segcmdo[0].initprot = segcmdo[0].maxprot = Mach_segment_command::VM_PROT_READ | Mach_segment_command::VM_PROT_WRITE | Mach_segment_command::VM_PROT_EXECUTE; - segcmdo.nsects = 0; - segcmdo.flags = 0; + segcmdo[0].nsects = 0; + segcmdo[0].flags = 0; + + segcmdo[1] = segcmdo[0]; + strncpy((char *)segcmdo[1].segname, "__LINKEDIT", sizeof(segcmdo[1].segname)); + segcmdo[1].initprot = Mach_segment_command::VM_PROT_READ; + // Adjust later: .vmaddr .vmsize .fileoff .filesize + if (my_filetype==Mach_header::MH_EXECUTE) { fo->write(&segcmdo, sizeof(segcmdo)); pack1_setup_threado(fo); + memset(&linkedito, 0, sizeof(linkedito)); + fo->write(&linkedito, sizeof(linkedito)); } if (my_filetype==Mach_header::MH_DYLIB) { fo->write(rawmseg, mhdri.sizeofcmds); @@ -1086,7 +1134,11 @@ void PackMachBase::unpack(OutputFile *fo) fi->readx(&mhdri, sizeof(mhdri)); rawmseg = (Mach_segment_command *)new char[(unsigned) mhdri.sizeofcmds]; fi->readx(rawmseg, mhdri.sizeofcmds); - overlay_offset = sizeof(mhdri) + mhdri.sizeofcmds + sizeof(linfo); + + // FIXME forgot space left for LC_CODE_SIGNATURE; + // but PackUnix::canUnpack() sets overlay_offset anyway. + //overlay_offset = sizeof(mhdri) + mhdri.sizeofcmds + sizeof(linfo); + fi->seek(overlay_offset, SEEK_SET); p_info hbuf; fi->readx(&hbuf, sizeof(hbuf));