From fec69afb1d639cd28a5d77adc0fed1e2574c262a Mon Sep 17 00:00:00 2001 From: jdh8d <jdh8d@git.zephyr-software.com> Date: Mon, 22 Aug 2016 18:09:29 +0000 Subject: [PATCH] updates (all over the place) for CFI with multimodule support. Former-commit-id: 2bad6a3f6f42c8d3652ececdd4a2f48beec33344 --- .gitattributes | 4 + tools/ret_shadow_stack/rss_instrument.cpp | 4 +- tools/selective_cfi/SConscript | 3 + tools/selective_cfi/scfi_instr.cpp | 79 +++++++++++++------ .../zest_cfi_runtime/SConscript32 | 34 ++++++++ .../zest_cfi_runtime/SConscript64 | 35 ++++++++ .../selective_cfi/zest_cfi_runtime/SConstruct | 7 ++ .../zest_cfi_runtime/zest_dispatch64.s | 47 +++++++++++ tools/simple_cdi/scdi_instr.cpp | 5 +- tools/transforms/Rewrite_Utility.cpp | 39 +++++++++ tools/transforms/Rewrite_Utility.hpp | 4 + 11 files changed, 233 insertions(+), 28 deletions(-) create mode 100644 tools/selective_cfi/zest_cfi_runtime/SConscript32 create mode 100644 tools/selective_cfi/zest_cfi_runtime/SConscript64 create mode 100644 tools/selective_cfi/zest_cfi_runtime/SConstruct create mode 100644 tools/selective_cfi/zest_cfi_runtime/zest_dispatch64.s diff --git a/.gitattributes b/.gitattributes index 059005660..99cae336e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1134,6 +1134,10 @@ tools/selective_cfi/color_map.hpp -text tools/selective_cfi/scfi_driver.cpp -text tools/selective_cfi/scfi_instr.cpp -text tools/selective_cfi/scfi_instr.hpp -text +tools/selective_cfi/zest_cfi_runtime/SConscript32 -text +tools/selective_cfi/zest_cfi_runtime/SConscript64 -text +tools/selective_cfi/zest_cfi_runtime/SConstruct -text +tools/selective_cfi/zest_cfi_runtime/zest_dispatch64.s -text tools/simple_cdi/Makefile.in -text tools/simple_cdi/SConscript -text tools/simple_cdi/SConstruct -text diff --git a/tools/ret_shadow_stack/rss_instrument.cpp b/tools/ret_shadow_stack/rss_instrument.cpp index 401a500e7..c8ee2a972 100644 --- a/tools/ret_shadow_stack/rss_instrument.cpp +++ b/tools/ret_shadow_stack/rss_instrument.cpp @@ -69,7 +69,8 @@ virtual_offset_t getAvailableAddress(FileIR_t *p_virp) - +#if 0 +// moved to Rewrite_Utility.cpp static Instruction_t* addNewAssembly(FileIR_t* firp, Instruction_t *p_instr, string p_asm) { Instruction_t* newinstr; @@ -88,6 +89,7 @@ static Instruction_t* addNewAssembly(FileIR_t* firp, Instruction_t *p_instr, str return newinstr; } +#endif static Instruction_t* registerCallbackHandler64(FileIR_t* firp, Instruction_t *p_orig, string p_callbackHandler, int p_numArgs) diff --git a/tools/selective_cfi/SConscript b/tools/selective_cfi/SConscript index 1f4a127f3..8f1007abc 100644 --- a/tools/selective_cfi/SConscript +++ b/tools/selective_cfi/SConscript @@ -31,3 +31,6 @@ Default(install) +#lib32=SConscript("zest_cfi_runtime/SConscript", variant_dir="build32") +SConscript("zest_cfi_runtime/SConscript") # , variant_dir="build64") + diff --git a/tools/selective_cfi/scfi_instr.cpp b/tools/selective_cfi/scfi_instr.cpp index ab420e6eb..de49eceef 100644 --- a/tools/selective_cfi/scfi_instr.cpp +++ b/tools/selective_cfi/scfi_instr.cpp @@ -48,6 +48,8 @@ virtual_offset_t getAvailableAddress(FileIR_t *p_virp) +#if 0 +// moved to Rewrite_Utility.cpp static Instruction_t* addNewAssembly(FileIR_t* firp, Instruction_t *p_instr, string p_asm) { Instruction_t* newinstr; @@ -66,7 +68,6 @@ static Instruction_t* addNewAssembly(FileIR_t* firp, Instruction_t *p_instr, str return newinstr; } - static Instruction_t* addNewDatabits(FileIR_t* firp, Instruction_t *p_instr, string p_bits) { Instruction_t* newinstr; @@ -85,6 +86,7 @@ static Instruction_t* addNewDatabits(FileIR_t* firp, Instruction_t *p_instr, str return newinstr; } +#endif static Instruction_t* registerCallbackHandler64(FileIR_t* firp, Instruction_t *p_orig, string p_callbackHandler, int p_numArgs) @@ -595,13 +597,11 @@ void SCFI_Instrument::AddReturnCFIForExeNonce(Instruction_t* insn, ColoredSlotVa ret -> jmp shared shared: + and [rsp], 0x7ffffffff mov reg <- [ rsp ] cmp [reg], exe_nonce_value - jne ret_slow + jne slow ret - ret_slow: - pop ecx - jmp slow // with cfi_slow-path nonce. #endif @@ -1039,22 +1039,25 @@ static unsigned int add_to_scoop(const string &str, DataScoop_t* scoop) return oldend+1; }; - template<int ptrsize> -static unsigned int prefix_scoop(const string &str, DataScoop_t* scoop, FileIR_t* firp) +static void insert_into_scoop_at(const string &str, DataScoop_t* scoop, FileIR_t* firp, const unsigned int at) { // assert that this scoop is unpinned. may need to enable --step move_globals --step-option move_globals:--cfi assert(scoop->GetStart()->GetVirtualOffset()==0); int len=str.length(); - scoop->SetContents(str+scoop->GetContents()); + string new_scoop_contents=scoop->GetContents(); + new_scoop_contents.insert(at,str); + scoop->SetContents(new_scoop_contents); + virtual_offset_t oldend=scoop->GetEnd()->GetVirtualOffset(); virtual_offset_t newend=oldend+len; scoop->GetEnd()->SetVirtualOffset(newend); // update each reloc to point to the new location. - for_each(scoop->GetRelocations().begin(), scoop->GetRelocations().end(), [str](Relocation_t* reloc) + for_each(scoop->GetRelocations().begin(), scoop->GetRelocations().end(), [str,at](Relocation_t* reloc) { - reloc->SetOffset(reloc->GetOffset()+str.size()); + if(reloc->GetOffset()>=at) + reloc->SetOffset(reloc->GetOffset()+str.size()); }); @@ -1068,10 +1071,10 @@ static unsigned int prefix_scoop(const string &str, DataScoop_t* scoop, FileIR_t }); // for each scoop - for_each(firp->GetDataScoops().begin(), firp->GetDataScoops().end(), [&str,scoop,firp](DataScoop_t* scoop_to_update) + for_each(firp->GetDataScoops().begin(), firp->GetDataScoops().end(), [&str,scoop,firp,at](DataScoop_t* scoop_to_update) { // for each relocation for that scoop - for_each(scoop_to_update->GetRelocations().begin(), scoop_to_update->GetRelocations().end(), [&str,scoop,firp,scoop_to_update](Relocation_t* reloc) + for_each(scoop_to_update->GetRelocations().begin(), scoop_to_update->GetRelocations().end(), [&str,scoop,firp,scoop_to_update,at](Relocation_t* reloc) { // if it's a reloc that's wrt scoop DataScoop_t* wrt=dynamic_cast<DataScoop_t*>(reloc->GetWRT()); @@ -1088,7 +1091,8 @@ static unsigned int prefix_scoop(const string &str, DataScoop_t* scoop, FileIR_t case 4: { unsigned int val=*((unsigned int*)&contents.c_str()[reloc->GetOffset()]); - val +=str.size(); + if(val>=at) + val +=str.size(); contents.replace(reloc->GetOffset(), ptrsize, (const char*)&val, ptrsize); break; @@ -1096,7 +1100,8 @@ static unsigned int prefix_scoop(const string &str, DataScoop_t* scoop, FileIR_t case 8: { unsigned long long val=*((long long*)&contents.c_str()[reloc->GetOffset()]); - val +=str.size(); + if(val>=at) + val +=str.size(); contents.replace(reloc->GetOffset(), ptrsize, (const char*)&val, ptrsize); break; @@ -1111,8 +1116,12 @@ static unsigned int prefix_scoop(const string &str, DataScoop_t* scoop, FileIR_t }); }); +}; - return oldend+1; +template<int ptrsize> +static void prefix_scoop(const string &str, DataScoop_t* scoop, FileIR_t* firp) +{ + insert_into_scoop_at<ptrsize>(str,scoop,firp,0); }; @@ -1166,7 +1175,7 @@ void SCFI_Instrument::add_got_entry(const std::string& name) AddressID_t* start_addr=new AddressID_t(BaseObj_t::NOT_IN_DATABASE, firp->GetFile()->GetBaseID(), 0); AddressID_t* end_addr=new AddressID_t(BaseObj_t::NOT_IN_DATABASE, firp->GetFile()->GetBaseID(), ptrsize-1); DataScoop_t* external_func_addr_scoop=new DataScoop_t(BaseObj_t::NOT_IN_DATABASE, - "zest_cfi_added_"+name, start_addr,end_addr, NULL, 6, true, new_got_entry_str); + name, start_addr,end_addr, NULL, 6, true, new_got_entry_str); firp->GetAddresses().insert(start_addr); firp->GetAddresses().insert(end_addr); @@ -1183,14 +1192,30 @@ void SCFI_Instrument::add_got_entry(const std::string& name) string dl_sym_str((const char*)&dl_sym, sizeof(T_Elf_Sym)); unsigned int dl_pos=add_to_scoop(dl_sym_str,dynsym_scoop); - // add reloc to binary + // find the rela count. can't insert before that. + int rela_count=0; + for(int i=0;i+sizeof(T_Elf_Dyn)<dynamic_scoop->GetSize(); i+=sizeof(T_Elf_Dyn)) + { + T_Elf_Dyn &dyn_entry=*(T_Elf_Dyn*)&dynamic_scoop->GetContents().c_str()[i]; + if(dyn_entry.d_tag==DT_RELACOUNT) // diff than rela size. + { + // add to the size + rela_count=dyn_entry.d_un.d_val; + break; + } + } + + // create the new reloc T_Elf_Rela dl_rel; memset(&dl_rel,0,sizeof(dl_rel)); dl_rel.r_info= ((dl_pos/sizeof(T_Elf_Sym))<<rela_shift) | reloc_type; string dl_rel_str((const char*)&dl_rel, sizeof(dl_rel)); - unsigned dl_rel_pos=prefix_scoop<ptrsize>(dl_rel_str, relscoop, firp); - Relocation_t* dl_reloc=new Relocation_t(BaseObj_t::NOT_IN_DATABASE, 0+((uintptr_t)&dl_rel.r_offset -(uintptr_t)&dl_rel), "dataptr_to_scoop", external_func_addr_scoop); +// need to fixup relocs + unsigned int at=rela_count*sizeof(T_Elf_Rela); + insert_into_scoop_at<ptrsize>(dl_rel_str, relscoop, firp, at); + + Relocation_t* dl_reloc=new Relocation_t(BaseObj_t::NOT_IN_DATABASE, at+((uintptr_t)&dl_rel.r_offset -(uintptr_t)&dl_rel), "dataptr_to_scoop", external_func_addr_scoop); relscoop->GetRelocations().insert(dl_reloc); firp->GetRelocations().insert(dl_reloc); @@ -1202,9 +1227,13 @@ void SCFI_Instrument::add_got_entry(const std::string& name) if(dyn_entry.d_tag==DT_RELASZ) // add to the size dyn_entry.d_un.d_val+=sizeof(T_Elf_Rela); - if(dyn_entry.d_tag==DT_RELA) + + // we insert the zest_cfi_dispatch symbol after the relative relocs. + // but we need to adjust the start if there are no relative relocs. + if(at == 0 && dyn_entry.d_tag==DT_RELA) // subtract from the start. dyn_entry.d_un.d_val-=sizeof(T_Elf_Rela); + } } @@ -1226,10 +1255,10 @@ bool SCFI_Instrument::add_got_entries() // add necessary GOT entries. - add_got_entry<T_Elf_Sym,T_Elf_Rela,T_Elf_Dyn,reloc_type,rela_shift,ptrsize>("printf"); - add_got_entry<T_Elf_Sym,T_Elf_Rela,T_Elf_Dyn,reloc_type,rela_shift,ptrsize>("dladdr"); - add_got_entry<T_Elf_Sym,T_Elf_Rela,T_Elf_Dyn,reloc_type,rela_shift,ptrsize>("dlopen"); - add_got_entry<T_Elf_Sym,T_Elf_Rela,T_Elf_Dyn,reloc_type,rela_shift,ptrsize>("dlsym"); + add_got_entry<T_Elf_Sym,T_Elf_Rela,T_Elf_Dyn,reloc_type,rela_shift,ptrsize>("zest_cfi_dispatch"); +// add_got_entry<T_Elf_Sym,T_Elf_Rela,T_Elf_Dyn,reloc_type,rela_shift,ptrsize>("dlopen"); +// add_got_entry<T_Elf_Sym,T_Elf_Rela,T_Elf_Dyn,reloc_type,rela_shift,ptrsize>("printf"); +// add_got_entry<T_Elf_Sym,T_Elf_Rela,T_Elf_Dyn,reloc_type,rela_shift,ptrsize>("dlsym"); // also add a zest cfi "function" that's exported so dlsym can find it. @@ -1294,7 +1323,7 @@ bool SCFI_Instrument::add_libdl_as_needed_support() assert(relaplt_scoop != NULL || relplt_scoop!=NULL); // can't have neither - auto libld_str_pos=add_to_scoop(string("libdl.so")+'\0', dynstr_scoop); + auto libld_str_pos=add_to_scoop(string("libzestcfi.so")+'\0', dynstr_scoop); // a new dt_needed entry for libdl.so diff --git a/tools/selective_cfi/zest_cfi_runtime/SConscript32 b/tools/selective_cfi/zest_cfi_runtime/SConscript32 new file mode 100644 index 000000000..705492944 --- /dev/null +++ b/tools/selective_cfi/zest_cfi_runtime/SConscript32 @@ -0,0 +1,34 @@ +import os + + +Import('env') +myenv=env.Clone() +myenv.Replace(SECURITY_TRANSFORMS_HOME=os.environ['SECURITY_TRANSFORMS_HOME']) +myenv.Replace(ZEST_RUNTIME=os.environ['ZEST_RUNTIME']) + +cpppath=''' + ''' + + +cfiles=Glob( Dir('.').srcnode().abspath+"/*.cpp") +nasmfiles32=Glob( Dir('.').srcnode().abspath+"/*32.s") + +CXXFLAGS = " -nostdlib -nostdinc -fno-exceptions -Wall " +CFLAGS = " -nostdlib -nostdinc -fno-exceptions -Wall " +LDFLAGS = " -nostdlib -nostdinc -fno-exceptions -Wall " +AS = "nasm" + +myenv.Replace(AS = AS) +myenv.Append(CPPPATH=Split(cpppath)) + +myenv.Replace(ASFLAGS = " -felf32 " ) +myenv.Append(CXXFLAGS = CXXFLAGS+" -m32 ") +myenv.Append(CFLAGS = CFLAGS+" -m32 ") +myenv.Append(LINKFLAGS = LDFLAGS+" -m32 ") + + +so32=myenv.SharedLibrary("libzestcfi32.so", cfiles+nasmfiles32) +install32=myenv.Install("$ZEST_RUNTIME/lib32/", so32) +Default(install32) + + diff --git a/tools/selective_cfi/zest_cfi_runtime/SConscript64 b/tools/selective_cfi/zest_cfi_runtime/SConscript64 new file mode 100644 index 000000000..35add780f --- /dev/null +++ b/tools/selective_cfi/zest_cfi_runtime/SConscript64 @@ -0,0 +1,35 @@ +import os + + +Import('env') +myenv=env.Clone() +myenv.Replace(SECURITY_TRANSFORMS_HOME=os.environ['SECURITY_TRANSFORMS_HOME']) +myenv.Replace(ZEST_RUNTIME=os.environ['ZEST_RUNTIME']) + +cpppath=''' + ''' + + +cfiles=Glob( Dir('.').srcnode().abspath+"/*.cpp")+Glob( Dir('.').srcnode().abspath+"/*.c") +nasmfiles64=Glob( Dir('.').srcnode().abspath+"/*64.s") + +CXXFLAGS = " -nostdlib -fno-exceptions -Wall -fPIC -g " +CFLAGS = " -nostdlib -fno-exceptions -Wall -fPIC -g " +LDFLAGS = " -nostdlib -fno-exceptions -Wall -fPIC -g " +AS = "nasm" + +myenv.Replace(AS = AS) +myenv.Append(CPPPATH=Split(cpppath)) + +myenv.Replace(ASFLAGS = " -felf64 ") +myenv.Append(CXXFLAGS = CXXFLAGS +" -m64 ") +myenv.Append(CFLAGS = CFLAGS +" -m64 ") +myenv.Append(LINKFLAGS = LDFLAGS +" -m64 ") + + +so64=myenv.SharedLibrary("libzestcfi.so", cfiles+nasmfiles64) +install64=myenv.Install("$ZEST_RUNTIME/lib64/", so64) +Default(install64) + + + diff --git a/tools/selective_cfi/zest_cfi_runtime/SConstruct b/tools/selective_cfi/zest_cfi_runtime/SConstruct new file mode 100644 index 000000000..e47f36c51 --- /dev/null +++ b/tools/selective_cfi/zest_cfi_runtime/SConstruct @@ -0,0 +1,7 @@ + + + +env=Environment() +Export('env') +#env.SConscript('SConscript32', variant_dir='/tmp/build32') +env.SConscript('SConscript64', variant_dir='/tmp/build64') diff --git a/tools/selective_cfi/zest_cfi_runtime/zest_dispatch64.s b/tools/selective_cfi/zest_cfi_runtime/zest_dispatch64.s new file mode 100644 index 000000000..4b75848d6 --- /dev/null +++ b/tools/selective_cfi/zest_cfi_runtime/zest_dispatch64.s @@ -0,0 +1,47 @@ +BITS 64 + +default rel + +extern zest_cfi_dispatch_c + +section .text +global zest_cfi_dispatch:function +zest_cfi_dispatch: + + lea rsp, [rsp-128] + pushf + push rax + push rbx + push rcx + push rdx + push rsi + push rdi + push rbp + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + mov rdi, r11 ; r11 is the cfi reg for x86-64, copy it to rdi for C-calling convention. + call zest_cfi_dispatch_c wrt ..plt + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rbp + pop rdi + pop rsi + pop rdx + pop rcx + pop rbx + pop rax + popf + lea rsp, [rsp+128] + ret diff --git a/tools/simple_cdi/scdi_instr.cpp b/tools/simple_cdi/scdi_instr.cpp index cc64ecc18..e8765e58f 100644 --- a/tools/simple_cdi/scdi_instr.cpp +++ b/tools/simple_cdi/scdi_instr.cpp @@ -48,7 +48,8 @@ std::string int_to_hex_string( T i ) - +#if 0 +// moved to Rewrite_Utility.cpp static Instruction_t* addNewAssembly(FileIR_t* firp, Instruction_t *p_instr, string p_asm) { Instruction_t* newinstr; @@ -67,7 +68,7 @@ static Instruction_t* addNewAssembly(FileIR_t* firp, Instruction_t *p_instr, str return newinstr; } - +#endif static Instruction_t* registerCallbackHandler64(FileIR_t* firp, Instruction_t *p_orig, string p_callbackHandler, int p_numArgs) { diff --git a/tools/transforms/Rewrite_Utility.cpp b/tools/transforms/Rewrite_Utility.cpp index e162173be..ccbdbb9b5 100644 --- a/tools/transforms/Rewrite_Utility.cpp +++ b/tools/transforms/Rewrite_Utility.cpp @@ -158,6 +158,45 @@ Instruction_t* allocateNewInstruction(FileIR_t* virp, db_id_t p_fileID,Function_ return instr; } +Instruction_t* addNewAssembly(FileIR_t* firp, Instruction_t *p_instr, string p_asm) +{ + Instruction_t* newinstr; + if (p_instr) + newinstr = allocateNewInstruction(firp,p_instr->GetAddress()->GetFileID(), p_instr->GetFunction()); + else + newinstr = allocateNewInstruction(firp,BaseObj_t::NOT_IN_DATABASE, NULL); + + firp->RegisterAssembly(newinstr, p_asm); + + if (p_instr) + { + newinstr->SetFallthrough(p_instr->GetFallthrough()); + p_instr->SetFallthrough(newinstr); + } + + return newinstr; +} + +Instruction_t* addNewDatabits(FileIR_t* firp, Instruction_t *p_instr, string p_bits) +{ + Instruction_t* newinstr; + if (p_instr) + newinstr = allocateNewInstruction(firp,p_instr->GetAddress()->GetFileID(), p_instr->GetFunction()); + else + newinstr = allocateNewInstruction(firp,BaseObj_t::NOT_IN_DATABASE, NULL); + + newinstr->SetDataBits(p_bits); + + if (p_instr) + { + newinstr->SetFallthrough(p_instr->GetFallthrough()); + p_instr->SetFallthrough(newinstr); + } + + return newinstr; +} + + Instruction_t* allocateNewInstruction(FileIR_t* virp, Instruction_t *template_instr) { Function_t *func = template_instr->GetFunction(); diff --git a/tools/transforms/Rewrite_Utility.hpp b/tools/transforms/Rewrite_Utility.hpp index c8a7b572f..b4b115c46 100644 --- a/tools/transforms/Rewrite_Utility.hpp +++ b/tools/transforms/Rewrite_Utility.hpp @@ -46,6 +46,10 @@ Instruction_t* insertAssemblyAfter(FileIR_t* virp, Instruction_t* first, string Instruction_t* insertAssemblyAfter(FileIR_t* virp, Instruction_t* first, string assembly); Instruction_t* insertDataBitsAfter(FileIR_t* virp, Instruction_t* first, string dataBits, Instruction_t *target); Instruction_t* insertDataBitsAfter(FileIR_t* virp, Instruction_t* first, string dataBits); +Instruction_t* addNewDatabits(FileIR_t* firp, Instruction_t *p_instr, string p_bits); +Instruction_t* addNewAssembly(FileIR_t* firp, Instruction_t *p_instr, string p_asm); + + //Does not insert into any variant, just copies data about the instruction itself, see the copyInstruction(src,dest) to see what is copied. Instruction_t* copyInstruction(Instruction_t* instr); -- GitLab