From e840e1e9d3377b49489d0ed39f2ee03c8fee9e2d Mon Sep 17 00:00:00 2001
From: mm8bx <mm8bx@git.zephyr-software.com>
Date: Mon, 30 Apr 2018 18:01:51 +0000
Subject: [PATCH] Fixed cactusADM bug in scfi_instr.cpp

Former-commit-id: e192d674d995ba52a2398730801353c89e9bcbea
---
 tools/selective_cfi/scfi_instr.cpp | 78 ++++++++++++++++++++----------
 1 file changed, 52 insertions(+), 26 deletions(-)

diff --git a/tools/selective_cfi/scfi_instr.cpp b/tools/selective_cfi/scfi_instr.cpp
index b11751cc0..caaed2f1e 100644
--- a/tools/selective_cfi/scfi_instr.cpp
+++ b/tools/selective_cfi/scfi_instr.cpp
@@ -370,43 +370,69 @@ void SCFI_Instrument::AddJumpCFI(Instruction_t* insn)
 #endif
 }
 
-
+//TODO: Does not work with coloring
 void SCFI_Instrument::AddCallCFIWithExeNonce(Instruction_t* insn)
 {
-	// make a stub to call
+	string reg="ecx";       // 32-bit reg 
+        if(firp->GetArchitectureBitWidth()==64)
+                reg="r11";      // 64-bit reg.
+
+	string decoration="";
+        int nonce_size=GetNonceSize(insn);
+        int nonce_offset=GetNonceOffset(insn);
+        unsigned int nonce=GetNonce(insn);
+        Instruction_t* call=NULL, *jne=NULL, *stub=NULL;
 
-        // the stub is:
-        //      push [target]
-        //      ret     
-        string pushbits=change_to_push(insn);
-        Instruction_t* stub=addNewDatabits(firp,NULL,pushbits);
-        stub->SetComment(insn->GetComment()+" cfi stub");
 
-        string retBits=getRetDataBits();
-        Instruction_t* ret=insertDataBitsAfter(firp, stub, retBits);
+        // convert a call indtarg to:
+	//      push indtarg  ;Calculate target if it has a memory operation
+        //      pop reg       ;Calculate it before changing stack ptr with call stub
+	//	call stub     ;Easy way to get correct return address on stack
+	//
+        //stub: cmp <nonce size> PTR [ecx-<nonce size>], Nonce
+        //      jne slow
+	//	jmp reg          
+
+        switch(nonce_size)
+        {
+                case 1:
+                        decoration="byte ";
+                        break;
+                case 2: // handle later
+                case 4: // handle later
+                default:
+                        cerr<<"Cannot handle nonce of size "<<std::dec<<nonce_size<<endl;
+                        assert(0);
 
-        assert(stub->GetFallthrough()==ret);
-        AddReturnCFI(ret);
+        }
 
-	/*string jmpBits=getJumpDataBits();
-	Instruction_t* jmp=insertDataBitsAfter(firp, stub, jmpBits);
+        // insert the pop/checking code.
+	string pushbits=change_to_push(insn);
+   call=insertDataBitsBefore(firp, insn, pushbits);
+        insertAssemblyAfter(firp,insn,string("pop ")+reg);
 
-	assert(stub->GetFallthrough()==jmp);
+        stub=addNewAssembly(firp,stub,string("cmp ")+decoration+
+                " ["+reg+"-"+to_string(nonce_offset)+"], "+to_string(nonce));
+        jne=insertAssemblyAfter(firp,stub,"jne 0");
+	insertAssemblyAfter(firp,jne,string("jmp ")+reg);
 
-	// create a reloc so the stub goes to the slow path, eventually
-	createNewRelocation(firp,jmp,"slow_cfi_path",0);
-	jmp->SetFallthrough(NULL);
-	jmp->SetTarget(jmp);	// looks like infinite loop, but will go to slow apth*/
+        // set the jne's target to itself, and create a reloc that zipr/strata will have to resolve.
+        jne->SetTarget(jne);    // needed so spri/spasm/irdb don't freak out about missing target for new insn.
+        Relocation_t* reloc=create_reloc(jne);
+        reloc->SetType("slow_cfi_path");
+        reloc->SetOffset(0);
+        cout<<"Setting slow path for: "<<"slow_cfi_path"<<endl;
 
 	// convert the indirct call to a direct call to the stub.
-	string call_bits=insn->GetDataBits();
-	call_bits.resize(5);
-	call_bits[0]=0xe8;
-	insn->SetTarget(stub);
-	insn->SetDataBits(call_bits);
-	insn->SetComment("Direct call to cfi stub");
-	insn->SetIBTargets(NULL);	// lose info about branch targets.
+        string call_bits=call->GetDataBits();
+        call_bits.resize(5);
+        call_bits[0]=0xe8;
+        call->SetTarget(stub);
+        call->SetDataBits(call_bits);
+        call->SetComment("Direct call to cfi stub");
+        call->SetIBTargets(NULL);       // lose info about branch targets.
 
+	return;
 }
 
 void SCFI_Instrument::AddExecutableNonce(Instruction_t* insn)
-- 
GitLab