From b36c65e6540265a22abc01b3258e70cb491ea42c Mon Sep 17 00:00:00 2001 From: John Reiser Date: Sat, 4 Aug 2012 16:44:21 -0700 Subject: [PATCH] fix Mac OS X code signing; also leave room for LC_UUID --- src/p_mach.cpp | 160 ++++++++++++++++++++++++++++++------------------- src/p_mach.h | 25 +++++++- 2 files changed, 122 insertions(+), 63 deletions(-) diff --git a/src/p_mach.cpp b/src/p_mach.cpp index 11636cb7..b385c481 100644 --- a/src/p_mach.cpp +++ b/src/p_mach.cpp @@ -351,7 +351,8 @@ 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[0].vmsize += h.sz_unc - h.sz_cpr + GAP + NO_LAP; + segTEXT.vmsize += h.sz_unc - h.sz_cpr + GAP + NO_LAP; + secTEXT.size += h.sz_unc - h.sz_cpr + GAP + NO_LAP; addStubEntrySections(ft); @@ -476,23 +477,29 @@ PackMachBase::compare_segment_command(void const *const aa, void const *const 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); + overlay_offset = sizeof(mhdro) + sizeof(segTEXT) + sizeof(secTEXT) + + sizeof(segLINK) + sizeof(threado) + sizeof(linfo); if (my_filetype==Mach_header::MH_EXECUTE) { - overlay_offset += sizeof(linkedito); + overlay_offset += sizeof(uuid_cmd) + sizeof(linkitem); } 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; + segTEXT.vmsize = segTEXT.filesize = fo->getBytesWritten(); + secTEXT.offset = overlay_offset - sizeof(linfo); + secTEXT.addr = segTEXT.vmaddr + secTEXT.offset; + secTEXT.size = segTEXT.vmsize - secTEXT.offset; + unsigned const foff1 = (PAGE_MASK & (~PAGE_MASK + segTEXT.filesize)); + segLINK.fileoff = foff1; + segLINK.vmaddr = segTEXT.vmaddr + foff1; fo->seek(foff1 - 1, SEEK_SET); fo->write("", 1); fo->seek(sizeof(mhdro), SEEK_SET); - fo->rewrite(&segcmdo, sizeof(segcmdo)); + fo->rewrite(&segTEXT, sizeof(segTEXT)); + fo->rewrite(&secTEXT, sizeof(secTEXT)); + fo->rewrite(&segLINK, sizeof(segLINK)); fo->rewrite(&threado, sizeof(threado)); if (my_filetype==Mach_header::MH_EXECUTE) { - fo->rewrite(&linkedito, sizeof(linkedito)); + fo->rewrite(&uuid_cmd, sizeof(uuid_cmd)); + fo->rewrite(&linkitem, sizeof(linkitem)); } fo->rewrite(&linfo, sizeof(linfo)); } @@ -500,23 +507,29 @@ void PackMachPPC32::pack4(OutputFile *fo, Filter &ft) // append PackHeader 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); + overlay_offset = sizeof(mhdro) + sizeof(segTEXT) + sizeof(secTEXT) + + sizeof(segLINK) + sizeof(threado) + sizeof(linfo); if (my_filetype==Mach_header::MH_EXECUTE) { - overlay_offset += sizeof(linkedito); + overlay_offset += sizeof(uuid_cmd) + sizeof(linkitem); } 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; + segTEXT.vmsize = segTEXT.filesize = fo->getBytesWritten(); + secTEXT.offset = overlay_offset - sizeof(linfo); + secTEXT.addr = segTEXT.vmaddr + secTEXT.offset; + secTEXT.size = segTEXT.vmsize - secTEXT.offset; + unsigned const foff1 = (PAGE_MASK & (~PAGE_MASK + segTEXT.filesize)); + segLINK.fileoff = foff1; + segLINK.vmaddr = segTEXT.vmaddr + foff1; fo->seek(foff1 - 1, SEEK_SET); fo->write("", 1); fo->seek(sizeof(mhdro), SEEK_SET); - fo->rewrite(&segcmdo, sizeof(segcmdo)); + fo->rewrite(&segTEXT, sizeof(segTEXT)); + fo->rewrite(&secTEXT, sizeof(secTEXT)); + fo->rewrite(&segLINK, sizeof(segLINK)); fo->rewrite(&threado, sizeof(threado)); if (my_filetype==Mach_header::MH_EXECUTE) { - fo->rewrite(&linkedito, sizeof(linkedito)); + fo->rewrite(&uuid_cmd, sizeof(uuid_cmd)); + fo->rewrite(&linkitem, sizeof(linkitem)); } fo->rewrite(&linfo, sizeof(linfo)); } @@ -524,23 +537,29 @@ void PackMachI386::pack4(OutputFile *fo, Filter &ft) // append PackHeader 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); + overlay_offset = sizeof(mhdro) + sizeof(segTEXT) + sizeof(secTEXT) + + sizeof(segLINK) + sizeof(threado) + sizeof(linfo); if (my_filetype==Mach_header::MH_EXECUTE) { - overlay_offset += sizeof(linkedito); + overlay_offset += sizeof(uuid_cmd) + sizeof(linkitem); } 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; + segTEXT.vmsize = segTEXT.filesize = fo->getBytesWritten(); + secTEXT.offset = overlay_offset - sizeof(linfo); + secTEXT.addr = segTEXT.vmaddr + secTEXT.offset; + secTEXT.size = segTEXT.vmsize - secTEXT.offset; + unsigned const foff1 = (PAGE_MASK & (~PAGE_MASK + segTEXT.filesize)); + segLINK.fileoff = foff1; + segLINK.vmaddr = segTEXT.vmaddr + foff1; fo->seek(foff1 - 1, SEEK_SET); fo->write("", 1); fo->seek(sizeof(mhdro), SEEK_SET); - fo->rewrite(&segcmdo, sizeof(segcmdo)); + fo->rewrite(&segTEXT, sizeof(segTEXT)); + fo->rewrite(&secTEXT, sizeof(secTEXT)); + fo->rewrite(&segLINK, sizeof(segLINK)); fo->rewrite(&threado, sizeof(threado)); if (my_filetype==Mach_header::MH_EXECUTE) { - fo->rewrite(&linkedito, sizeof(linkedito)); + fo->rewrite(&uuid_cmd, sizeof(uuid_cmd)); + fo->rewrite(&linkitem, sizeof(linkitem)); } fo->rewrite(&linfo, sizeof(linfo)); } @@ -548,23 +567,29 @@ void PackMachAMD64::pack4(OutputFile *fo, Filter &ft) // append PackHeader 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); + overlay_offset = sizeof(mhdro) + sizeof(segTEXT) + sizeof(secTEXT) + + sizeof(segLINK) + sizeof(threado) + sizeof(linfo); if (my_filetype==Mach_header::MH_EXECUTE) { - overlay_offset += sizeof(linkedito); + overlay_offset += sizeof(uuid_cmd) + sizeof(linkitem); } 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; + segTEXT.vmsize = segTEXT.filesize = fo->getBytesWritten(); + secTEXT.offset = overlay_offset - sizeof(linfo); + secTEXT.addr = segTEXT.vmaddr + secTEXT.offset; + secTEXT.size = segTEXT.vmsize - secTEXT.offset; + unsigned const foff1 = (PAGE_MASK & (~PAGE_MASK + segTEXT.filesize)); + segLINK.fileoff = foff1; + segLINK.vmaddr = segTEXT.vmaddr + foff1; fo->seek(foff1 - 1, SEEK_SET); fo->write("", 1); fo->seek(sizeof(mhdro), SEEK_SET); - fo->rewrite(&segcmdo, sizeof(segcmdo)); + fo->rewrite(&segTEXT, sizeof(segTEXT)); + fo->rewrite(&secTEXT, sizeof(secTEXT)); + fo->rewrite(&segLINK, sizeof(segLINK)); fo->rewrite(&threado, sizeof(threado)); if (my_filetype==Mach_header::MH_EXECUTE) { - fo->rewrite(&linkedito, sizeof(linkedito)); + fo->rewrite(&uuid_cmd, sizeof(uuid_cmd)); + fo->rewrite(&linkitem, sizeof(linkitem)); } fo->rewrite(&linfo, sizeof(linfo)); } @@ -777,7 +802,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[0].vmaddr; /* entry address */ + threado.state.srr0 = len + segTEXT.vmaddr; /* entry address */ super::pack3(fo, ft); } @@ -791,7 +816,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[0].vmaddr; /* entry address */ + threado.state.eip = len + sizeof(disp) + segTEXT.vmaddr; /* entry address */ super::pack3(fo, ft); } @@ -805,7 +830,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[0].vmaddr; /* entry address */ + threado.state.rip = len + sizeof(disp) + segTEXT.vmaddr; /* entry address */ super::pack3(fo, ft); } @@ -819,7 +844,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[0].vmaddr; /* entry address */ + threado.state.pc = len + sizeof(disp) + segTEXT.vmaddr; /* entry address */ super::pack3(fo, ft); } @@ -1027,7 +1052,8 @@ 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[0].filesize = fo->getBytesWritten(); + segTEXT.filesize = fo->getBytesWritten(); + secTEXT.size = segTEXT.filesize - overlay_offset + sizeof(linfo); return 1; } @@ -1078,42 +1104,54 @@ 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 = 3; - mhdro.sizeofcmds = sizeof(segcmdo) + my_thread_command_size; + mhdro.ncmds = 3; // __TEXT, __LINKEDIT, THREAD_STATE + mhdro.sizeofcmds = sizeof(segTEXT) + sizeof(secTEXT) + sizeof(segLINK) + + my_thread_command_size /* + sizeof(uuid_cmd) + sizeof(linkitem) */ ; mhdro.flags = Mach_header::MH_NOUNDEFS; } fo->write(&mhdro, sizeof(mhdro)); - segcmdo[0].cmd = lc_seg; - segcmdo[0].cmdsize = sizeof(segcmdo[0]); - strncpy((char *)segcmdo[0].segname, "__TEXT", sizeof(segcmdo[0].segname)); + segTEXT.cmd = lc_seg; + segTEXT.cmdsize = sizeof(segTEXT) + sizeof(secTEXT); + strncpy((char *)segTEXT.segname, "__TEXT", sizeof(segTEXT.segname)); if (my_filetype==Mach_header::MH_EXECUTE) { - segcmdo[0].vmaddr = PAGE_MASK64 & (~PAGE_MASK64 + + segTEXT.vmaddr = PAGE_MASK64 & (~PAGE_MASK64 + msegcmd[n_segment -1].vmsize + msegcmd[n_segment -1].vmaddr ); } if (my_filetype==Mach_header::MH_DYLIB) { - segcmdo[0].vmaddr = 0; + segTEXT.vmaddr = 0; } - segcmdo[0].vmsize = 0; // adjust later - segcmdo[0].fileoff = 0; - segcmdo[0].filesize = 0; // adjust later - segcmdo[0].initprot = segcmdo[0].maxprot = + segTEXT.vmsize = 0; // adjust later + segTEXT.fileoff = 0; + segTEXT.filesize = 0; // adjust later + segTEXT.initprot = segTEXT.maxprot = Mach_segment_command::VM_PROT_READ | Mach_segment_command::VM_PROT_WRITE | Mach_segment_command::VM_PROT_EXECUTE; - segcmdo[0].nsects = 0; - segcmdo[0].flags = 0; + segTEXT.nsects = 1; // secTEXT + segTEXT.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; + memset(&secTEXT, 0, sizeof(secTEXT)); + strncpy((char *)secTEXT.sectname, "__text", sizeof(secTEXT.sectname)); + memcpy(secTEXT.segname, segTEXT.segname, sizeof(secTEXT.segname)); + secTEXT.align = 2; // (1<<2) ==> 4 + + segLINK = segTEXT; + segLINK.cmdsize = sizeof(segLINK); + strncpy((char *)segLINK.segname, "__LINKEDIT", sizeof(segLINK.segname)); + segLINK.nsects = 0; + segLINK.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)); + fo->write(&segTEXT, sizeof(segTEXT)); + fo->write(&secTEXT, sizeof(secTEXT)); + fo->write(&segLINK, sizeof(segLINK)); pack1_setup_threado(fo); - memset(&linkedito, 0, sizeof(linkedito)); - fo->write(&linkedito, sizeof(linkedito)); + memset(&uuid_cmd, 0, sizeof(uuid_cmd)); + fo->write(&uuid_cmd, sizeof(uuid_cmd)); + memset(&linkitem, 0, sizeof(linkitem)); + fo->write(&linkitem, sizeof(linkitem)); } if (my_filetype==Mach_header::MH_DYLIB) { fo->write(rawmseg, mhdri.sizeofcmds); diff --git a/src/p_mach.h b/src/p_mach.h index 721963ba..fe09a64c 100644 --- a/src/p_mach.h +++ b/src/p_mach.h @@ -279,6 +279,15 @@ __packed_struct(Mach_linkedit_data_command) Word datasize; // file size of data in __LINKEDIT segment __packed_struct_end() +template +__packed_struct(Mach_uuid_command) + typedef typename TMachITypes::Word Word; + + Word cmd; + Word cmdsize; + unsigned char uuid[16]; +__packed_struct_end() + template __packed_struct(Mach_ppc_thread_state) typedef typename TMachITypes::Addr Addr; @@ -403,6 +412,7 @@ struct MachClass_32 typedef N_Mach::Mach_routines_command Mach_routines_command; typedef N_Mach::Mach_twolevel_hints_command Mach_twolevel_hints_command; typedef N_Mach::Mach_linkedit_data_command Mach_linkedit_data_command; + typedef N_Mach::Mach_uuid_command Mach_uuid_command; typedef N_Mach::Mach_ppc_thread_state Mach_ppc_thread_state; typedef N_Mach::Mach_i386_thread_state Mach_i386_thread_state; typedef N_Mach::Mach_AMD64_thread_state Mach_AMD64_thread_state; @@ -440,6 +450,7 @@ struct MachClass_64 typedef N_Mach::Mach_routines_command_64 Mach_routines_command; typedef N_Mach::Mach_twolevel_hints_command Mach_twolevel_hints_command; typedef N_Mach::Mach_linkedit_data_command Mach_linkedit_data_command; + typedef N_Mach::Mach_uuid_command Mach_uuid_command; static void compileTimeAssertions() { BeLePolicy::compileTimeAssertions(); @@ -465,6 +476,7 @@ typedef MachClass_Host32::Mach_segsplit_info_command Mach32_segsplit_info_comman typedef MachClass_Host32::Mach_routines_command Mach32_routines_command; typedef MachClass_Host32::Mach_twolevel_hints_command Mach32_twolevel_hints_command; typedef MachClass_Host32::Mach_linkedit_data_command Mach32_linkedit_data_command; +typedef MachClass_Host32::Mach_uuid_command Mach32_uuid_command; typedef MachClass_Host64::Mach_segment_command Mach64_segment_command; typedef MachClass_Host64::Mach_section_command Mach64_section_command; @@ -474,6 +486,7 @@ typedef MachClass_Host64::Mach_segsplit_info_command Mach64_segsplit_info_comman typedef MachClass_Host64::Mach_routines_command Mach64_routines_command; typedef MachClass_Host64::Mach_twolevel_hints_command Mach64_twolevel_hints_command; typedef MachClass_Host64::Mach_linkedit_data_command Mach64_linkedit_data_command; +typedef MachClass_Host64::Mach_uuid_command Mach64_uuid_command; typedef MachClass_BE32::Mach_segment_command MachBE32_segment_command; typedef MachClass_BE32::Mach_section_command MachBE32_section_command; @@ -483,6 +496,7 @@ typedef MachClass_BE32::Mach_segsplit_info_command MachBE32_segsplit_info_comm typedef MachClass_BE32::Mach_routines_command MachBE32_routines_command; typedef MachClass_BE32::Mach_twolevel_hints_command MachBE32_twolevel_hints_command; typedef MachClass_BE32::Mach_linkedit_data_command MachBE32_linkedit_data_command; +typedef MachClass_BE32::Mach_uuid_command MachBE32_uuid_command; typedef MachClass_BE64::Mach_segment_command MachBE64_segment_command; typedef MachClass_BE64::Mach_section_command MachBE64_section_command; @@ -492,6 +506,7 @@ typedef MachClass_BE64::Mach_segsplit_info_command MachBE64_segsplit_info_comm typedef MachClass_BE64::Mach_routines_command MachBE64_routines_command; typedef MachClass_BE64::Mach_twolevel_hints_command MachBE64_twolevel_hints_command; typedef MachClass_BE64::Mach_linkedit_data_command MachBE64_linkedit_data_command; +typedef MachClass_BE64::Mach_uuid_command MachBE64_uuid_command; typedef MachClass_LE32::Mach_segment_command MachLE32_segment_command; typedef MachClass_LE32::Mach_section_command MachLE32_section_command; @@ -501,6 +516,7 @@ typedef MachClass_LE32::Mach_segsplit_info_command MachLE32_segsplit_info_comm typedef MachClass_LE32::Mach_routines_command MachLE32_routines_command; typedef MachClass_LE32::Mach_twolevel_hints_command MachLE32_twolevel_hints_command; typedef MachClass_LE32::Mach_linkedit_data_command MachLE32_linkedit_data_command; +typedef MachClass_LE32::Mach_uuid_command MachLE32_uuid_command; typedef MachClass_LE64::Mach_segment_command MachLE64_segment_command; typedef MachClass_LE64::Mach_section_command MachLE64_section_command; @@ -510,6 +526,7 @@ typedef MachClass_LE64::Mach_segsplit_info_command MachLE64_segsplit_info_comm typedef MachClass_LE64::Mach_routines_command MachLE64_routines_command; typedef MachClass_LE64::Mach_twolevel_hints_command MachLE64_twolevel_hints_command; typedef MachClass_LE64::Mach_linkedit_data_command MachLE64_linkedit_data_command; +typedef MachClass_LE64::Mach_uuid_command MachLE64_uuid_command; typedef MachClass_BE32::Mach_ppc_thread_state Mach_ppc_thread_state; typedef MachClass_LE32::Mach_i386_thread_state Mach_i386_thread_state; @@ -541,6 +558,7 @@ protected: typedef typename MachClass::Mach_routines_command Mach_routines_command; typedef typename MachClass::Mach_twolevel_hints_command Mach_twolevel_hints_command; typedef typename MachClass::Mach_linkedit_data_command Mach_linkedit_data_command; + typedef typename MachClass::Mach_uuid_command Mach_uuid_command; public: PackMachBase(InputFile *, unsigned cpuid, unsigned filetype, @@ -594,8 +612,11 @@ protected: Mach_header mhdri; Mach_header mhdro; - Mach_segment_command segcmdo[2]; // __TEXT; __LINKEDIT (needed for code signing) - Mach_linkedit_data_command linkedito; + Mach_segment_command segTEXT; + Mach_section_command secTEXT; + Mach_segment_command segLINK; + Mach_linkedit_data_command linkitem; + Mach_uuid_command uuid_cmd; __packed_struct(b_info) // 12-byte header before each compressed block TE32 sz_unc; // uncompressed_size