Code cleanup

This commit is contained in:
Tobias Stumpf
2014-06-11 11:04:03 +02:00
parent 78a0d863a2
commit 53dc6bbf36
7 changed files with 27 additions and 443 deletions

View File

@ -20,8 +20,6 @@ set(MY_CAMPAIGN_SRCS
UDIS86.cc
InstructionFilter.hpp
InstructionFilter.cc
conversion.hpp
conversion.cc
)
#### PROTOBUFS ####

View File

@ -1,164 +1,12 @@
#include <iostream>
#include <fstream>
#include "campaign.hpp"
#include "experimentInfo.hpp"
#include "conversion.hpp"
#include "comm/DatabaseCampaignMessage.pb.h"
#include "experiment.hpp"
#include "cpn/CampaignManager.hpp"
#include "util/Logger.hpp"
#include "sal/SALConfig.hpp"
using namespace std;
using namespace fail;
char const * const results_csv = "l4sys.csv";
extern L4SysConversion l4sysResultConversion;
extern L4SysConversion l4sysExperimentConversion;
extern L4SysConversion l4sysRegisterConversion;
#if 0
bool L4SysCampaign::run() {
Logger log("L4SysCampaign");
ifstream test(results_csv);
if (test.is_open()) {
log << results_csv << " already exists" << endl;
return false;
}
ofstream results(results_csv);
if (!results.is_open()) {
log << "failed to open " << results_csv << endl;
return false;
}
log << "startup" << endl;
int count = 0;
srand(time(NULL));
for (int i = 0; i < L4SYS_NUMINSTR; ++i) {
for (int r = 1; r < 9; ++r) {
for (int b = 0; b < 32; ++b) {
L4SysExperimentData *d = new L4SysExperimentData;
d->msg.set_exp_type(d->msg.GPRFLIP);
d->msg.set_register_offset(static_cast<L4SysProtoMsg_RegisterType>(r));
d->msg.set_instr_offset(i);
d->msg.set_bit_offset(b);
campaignmanager.addParam(d);
++count;
}
}
}
for (int i = 0; i < 20000; ++i) {
L4SysExperimentData *d = new L4SysExperimentData;
d->msg.set_exp_type(d->msg.GPRFLIP);
// affect a random register
int reg_offset = rand() % 8 + 1;
d->msg.set_register_offset(
static_cast<L4SysProtoMsg_RegisterType>(reg_offset));
// modify for a random instruction
int instr_offset = rand() % L4SYS_NUMINSTR;
d->msg.set_instr_offset(instr_offset);
// modify a random bit
int bit_offset = rand() % 32;
d->msg.set_bit_offset(bit_offset);
campaignmanager.addParam(d);
++count;
}
for (int i = 0; i < 20000; ++i) {
L4SysExperimentData *d = new L4SysExperimentData;
d->msg.set_exp_type(d->msg.ALUINSTR);
// modify for a random instruction
int instr_offset = rand() % L4SYS_NUMINSTR;
d->msg.set_instr_offset(instr_offset);
// this value is not required for this experiment, so set it to an arbitrary value
d->msg.set_bit_offset(0);
campaignmanager.addParam(d);
++count;
}
for (int i = 0; i < 20000; ++i) {
L4SysExperimentData *d = new L4SysExperimentData;
d->msg.set_exp_type(d->msg.IDCFLIP);
// modify for a random instruction
int instr_offset = rand() % L4SYS_NUMINSTR;
d->msg.set_instr_offset(instr_offset);
// modify a random bit - Bochs supports at most 15 bytes of instruction
int bit_offset = rand() % 125;
d->msg.set_bit_offset(bit_offset);
campaignmanager.addParam(d);
++count;
}
for (int i = 0; i < 20000; ++i) {
L4SysExperimentData *d = new L4SysExperimentData;
d->msg.set_exp_type(d->msg.RATFLIP);
// modify for a random instruction
int instr_offset = rand() % L4SYS_NUMINSTR;
d->msg.set_instr_offset(instr_offset);
// this value is not required for this experiment, so set it to an arbitrary value
d->msg.set_bit_offset(0);
campaignmanager.addParam(d);
++count;
}
campaignmanager.noMoreParameters();
log << "done enqueueing parameter sets (" << count << ")." << endl;
// collect results
L4SysExperimentData *res;
int rescount = 0;
results
<< "exp_type,injection_ip,register,instr_offset,injection_bit,resulttype,resultdata,output,details"
<< endl;
while ((res = static_cast<L4SysExperimentData *>(campaignmanager.getDone()))) {
rescount++;
results << l4sysExperimentConversion.output(res->msg.exp_type())
<< "," << hex << res->msg.injection_ip() << dec << ",";
if (res->msg.has_register_offset())
results << l4sysRegisterConversion.output(res->msg.register_offset());
else
results << "None";
results << "," << res->msg.instr_offset() << "," << res->msg.bit_offset()
<< ","
<< l4sysResultConversion.output(res->msg.resulttype()) << ","
<< res->msg.resultdata();
if (res->msg.has_output())
results << "," << res->msg.output();
if (res->msg.has_details())
results << "," << res->msg.details();
results << endl;
delete res;
}
log << "done. sent " << count << " received " << rescount << endl;
results.close();
return true;
}
#endif
using namespace google::protobuf;
void L4SysCampaign::cb_send_pilot(DatabaseCampaignMessage p)
{
#if 0
int inj_instr = p.injection_instr();
int data_addr = p.data_address();
int reg = (data_addr >> 8) & 0xF;
int width = (data_addr >> 4) & 0xF;
int offs = data_addr & 0xF;
#endif
L4SysExperimentData *d = new L4SysExperimentData;
d->msg.mutable_fsppilot()->CopyFrom(p);
d->msg.set_exp_type(d->msg.GPRFLIP);
//d->msg.set_exp_type(d->msg.MEM);
campaignmanager.addParam(d);
//d->msg.set_exp_type(d->msg.GPRFLIP);
d->msg.set_exp_type(d->msg.MEM);
fail::campaignmanager.addParam(d);
}

View File

@ -13,15 +13,10 @@ public:
};
class L4SysCampaign : public fail::DatabaseCampaign {
#if 0
public:
virtual bool run();
#else
virtual const google::protobuf::Descriptor * cb_result_message()
{ return google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName("L4SysProtoMsg"); }
virtual void cb_send_pilot(DatabaseCampaignMessage pilot);
#endif
};
#endif // __L4SYS_CAMPAIGN_HPP__

View File

@ -1,16 +0,0 @@
#include "conversion.hpp"
char const *l4sys_output_result_strings[] = { "Unknown", "No effect", "Incomplete execution", "Crash", "Silent data corruption", "Error" };
char const *l4sys_output_experiment_strings[] = { "Unknown", "GPR Flip", "RAT Flip", "IDC Flip", "ALU Instr Flip" };
char const *l4sys_output_register_strings[] = { "Unknown", "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI" };
L4SysConversion l4sysResultConversion(
l4sys_output_result_strings,
sizeof(l4sys_output_result_strings));
L4SysConversion l4sysExperimentConversion(
l4sys_output_experiment_strings,
sizeof(l4sys_output_experiment_strings));
L4SysConversion l4sysRegisterConversion(
l4sys_output_register_strings,
sizeof(l4sys_output_register_strings));

View File

@ -1,25 +0,0 @@
#ifndef __L4SYS_CONVERSION_HPP__
#define __L4SYS_CONVERSION_HPP__
#include "l4sys.pb.h"
class L4SysConversion {
public:
L4SysConversion(char const **strings, size_t array_size)
: m_Strings(strings)
{
m_ElementCount = array_size / sizeof(char*);
}
char const * output(unsigned int res) {
if (res == 0 || res >= m_ElementCount) {
return m_Strings[0];
} else {
return m_Strings[res];
}
}
private:
char const **m_Strings;
size_t m_ElementCount;
};
#endif // __L4SYS_CONVERSION_HPP__

View File

@ -36,9 +36,6 @@ using namespace fail;
save, and restore. Enable these in the configuration.
#endif
//string golden_run;
extern L4SysConversion l4sysRegisterConversion;
string L4SysExperiment::sanitised(const string &in_str) {
string result;
int in_str_size = in_str.size();
@ -474,8 +471,7 @@ void L4SysExperiment::collectInstructionTrace(fail::BPSingleListener* bp)
#if 0
if (curr_addr < 0xC0000000) // XXX filter for kernel-only experiment
continue;
#endif
#endif
currtime = simulator.getTimerTicks();
deltatime = currtime - prevtime;
@ -816,7 +812,7 @@ bool L4SysExperiment::run()
BPSingleListener ev_longjmp(L4SYS_BREAK_LONGJMP);
simulator.addListener(&ev_longjmp);
//If we come to our own exit function, we can stop
//If we come to our own exit function, we can stop
BPSingleListener ev_exit(L4SYS_BREAK_EXIT);
simulator.addListener(&ev_exit);
@ -844,10 +840,6 @@ bool L4SysExperiment::run()
<< (void*)&ev_incomplete << endl;
BaseListener *ev = afterInjection(result);
log << "afterInj: res.devstep = " << result->deviate_steps() << endl;
#if 0
//do not discard output recorded so far
BaseListener *ev = waitIOOrOther(false);
#endif
/* copying a string object that contains control sequences
* unfortunately does not work with the library I am using,
@ -875,11 +867,11 @@ bool L4SysExperiment::run()
result->set_resulttype(param->msg.TIMEOUT);
result->set_resultdata(simulator.getCPU(0).getInstructionPointer());
result->set_output(sanitised(currentOutput.c_str()));
} else if (ev == &ev_exit) {
log << "Result FAILSTOP" << endl;
result->set_resulttype(param->msg.FAILSTOP);
result->set_resultdata(simulator.getCPU(0).getInstructionPointer());
result->set_output(sanitised(currentOutput.c_str()));
} else if (ev == &ev_exit) {
log << "Result FAILSTOP" << endl;
result->set_resulttype(param->msg.FAILSTOP);
result->set_resultdata(simulator.getCPU(0).getInstructionPointer());
result->set_output(sanitised(currentOutput.c_str()));
} else {
log << "Result WTF?" << endl;
stringstream ss;
@ -890,220 +882,6 @@ bool L4SysExperiment::run()
m_jc.sendResult(*param);
// XXX: Fixme to work with database campaign!
#if 0
else if (exp_type == param->msg.IDCFLIP) {
// this is a twisted one
// initial definitions
bxInstruction_c *currInstr = simulator.getCurrentInstruction();
unsigned length_in_bits = currInstr->ilen() << 3;
// get the instruction in plain text and inject the error there
// Note: we need to fetch some extra bytes into the array
// in case the faulty instruction is interpreted to be longer
// than the original one
Bit8u curr_instr_plain[MAX_INSTR_BYTES];
const Bit8u *addr = calculateInstructionAddress();
memcpy(curr_instr_plain, addr, MAX_INSTR_BYTES);
// CampaignManager has no idea of the instruction length
// (neither do we), therefore this small adaption
bit_offset %= length_in_bits;
param->msg.set_bit_offset(bit_offset);
// do some access calculation
int byte_index = bit_offset >> 3;
Bit8u bit_index = bit_offset & 7;
// apply the fault
curr_instr_plain[byte_index] ^= 0x80 >> bit_index;
// decode the instruction
bxInstruction_c bochs_instr;
memset(&bochs_instr, 0, sizeof(bxInstruction_c));
fetchInstruction(simulator.getCPUContext(), curr_instr_plain,
&bochs_instr);
// inject it
injectInstruction(currInstr, &bochs_instr);
// do the logging
logInjection();
} else if (exp_type == param->msg.RATFLIP) {
ud_type_t which = UD_NONE;
unsigned rnd = 0;
Udis86 udis(injection_ip);
do {
bxInstruction_c *currInstr = simulator.getCurrentInstruction();
udis.setInputBuffer(calculateInstructionAddress(), currInstr->ilen());
if (!udis.fetchNextInstruction()) {
terminateWithError(
"Could not decode instruction using UDIS86", 32);
}
ud_t _ud = udis.getCurrentState();
/* start Bjoern Doebel's code (slightly modified) */
/* ============================================== */
unsigned opcount = 0;
unsigned operands[4] = { ~0U, ~0U, ~0U, ~0U };
enum {
RAT_IDX_MASK = 0x0FF,
RAT_IDX_OFFSET = 0x100
};
for (unsigned i = 0; i < 3; ++i) {
/*
* Case 1: operand is a register
*/
if (_ud.operand[i].type == UD_OP_REG) {
operands[opcount++] = i;
} else if (_ud.operand[i].type == UD_OP_MEM) {
/*
* Case 2: operand is memory op.
*
* In this case, we may have 2 registers involved for the
* index-scale address calculation.
*/
if (_ud.operand[i].base != 0) // 0 if hard-wired mem operand
operands[opcount++] = i;
if (_ud.operand[i].index != 0)
operands[opcount++] = i + RAT_IDX_OFFSET;
}
}
if (opcount == 0) {
// try the next instruction
singleStep(true);
} else {
// assign the necessary variables
rnd = rand() % opcount;
if (operands[rnd] > RAT_IDX_OFFSET) {
which = _ud.operand[operands[rnd] - RAT_IDX_OFFSET].index;
} else {
which = _ud.operand[operands[rnd]].base;
}
}
/* ============================================ */
/* end Bjoern Doebel's code (slightly modified) */
} while (which == UD_NONE &&
simulator.getCPU(0).getInstructionPointer() != L4SYS_FUNC_EXIT);
if (simulator.getCPU(0).getInstructionPointer() == L4SYS_FUNC_EXIT) {
stringstream ss;
ss << "Reached the end of the experiment ";
ss << "without finding an appropriate instruction";
terminateWithError(ss.str(), 33);
}
// store the real injection point
param->msg.set_injection_ip(simulator.getCPU(0).getInstructionPointer());
// so we are able to flip the associated registers
// for details on the algorithm, see Bjoern Doebel's SWIFI/RATFlip class
// some declarations
GPRegisterId bochs_reg = Udis86::udisGPRToFailBochsGPR(which);
param->msg.set_register_offset(static_cast<L4SysProtoMsg_RegisterType>(bochs_reg + 1));
ConcreteCPU &cpu = simulator.getCPU(0);
Register *bochsRegister = cpu.getRegister(bochs_reg);
Register *exchangeRegister = NULL;
// first, decide if the fault hits a register bound to this thread
// (ten percent chance)
if (rand() % 10 == 0) {
// assure exchange of registers
unsigned int exchg_reg = rand() % 7;
if (exchg_reg == bochs_reg)
exchg_reg++;
exchangeRegister = cpu.getRegister(exchg_reg);
param->msg.set_details(l4sysRegisterConversion.output(exchg_reg + 1));
}
// prepare the fault
regdata_t data = cpu.getRegisterContent(bochsRegister);
if (rnd > 0) {
//input register - do the fault injection here
regdata_t newdata = 0;
if (exchangeRegister != NULL) {
// the data is taken from a process register chosen before
newdata = cpu.getRegisterContent(exchangeRegister);
} else {
// the data comes from an uninitialised register
newdata = rand();
stringstream ss;
ss << "0x" << hex << newdata;
param->msg.set_details(ss.str());
}
cpu.setRegisterContent(bochsRegister, newdata);
}
// execute the instruction
singleStep(true);
// restore the register if we are still in the thread
if (rnd == 0) {
// output register - do the fault injection here
if (exchangeRegister != NULL) {
// write the result into the wrong local register
regdata_t newdata = cpu.getRegisterContent(bochsRegister);
cpu.setRegisterContent(exchangeRegister, newdata);
}
// otherwise, just assume it is stored in an unused register
}
// restore the actual value of the register
// in reality, it would never have been overwritten
cpu.setRegisterContent(bochsRegister, data);
// log the injection
logInjection();
} else if (exp_type == param->msg.ALUINSTR) {
static BochsALUInstructions aluInstrObject(aluInstructions, aluInstructionsSize);
// find the closest ALU instruction after the current IP
bxInstruction_c *currInstr;
while (!aluInstrObject.isALUInstruction(
currInstr = simulator.getCurrentInstruction()) &&
simulator.getCPU(0).getInstructionPointer() != L4SYS_FUNC_EXIT) {
singleStep(true);
}
if (simulator.getCPU(0).getInstructionPointer() == L4SYS_FUNC_EXIT) {
stringstream ss;
ss << "Reached the end of the experiment ";
ss << "without finding an appropriate instruction";
terminateWithError(ss.str(), 34);
}
// store the real injection point
param->msg.set_injection_ip(simulator.getCPU(0).getInstructionPointer());
// now exchange it with a random equivalent
bxInstruction_c newInstr;
string details;
aluInstrObject.randomEquivalent(newInstr, details);
if (memcmp(&newInstr, currInstr, sizeof(bxInstruction_c)) == 0) {
// something went wrong - exit experiment
terminateWithError(
"Did not hit an ALU instruction - correct the source code please!",
40);
}
// record information on the new instruction
param->msg.set_details(details);
// inject it
injectInstruction(currInstr, &newInstr);
// do the logging
logInjection();
}
#endif
#endif
terminate(0);

View File

@ -6,23 +6,29 @@
// the bounds of the program (space, instructions and time)
// client
#define L4SYS_ADDRESS_SPACE 0x1fd4c000
#define L4SYS_ADDRESS_SPACE 0x1fd77000
// server
#define L4SYS_ADDRESS_SPACE_TRACE L4SYS_ADDRESS_SPACE
//#define L4SYS_ADDRESS_SPACE_TRACE 0x1fd4c000
#define L4SYS_exp_start 0x20000216
#define L4SYS_exp_end 0x2000029c
#define L4SYS_inj_start 0x2000022f
#define L4SYS_inj_end 0x20000252
// FUNC_{ENTRY,EXIT} specifies the range that needs to
// be captured to log program output properly
#define L4SYS_FUNC_ENTRY 0x20000220
#define L4SYS_FUNC_EXIT 0x20000216
#define L4SYS_FUNC_ENTRY L4SYS_exp_start
#define L4SYS_FUNC_EXIT L4SYS_exp_end
// FILTER_{ENTRY,EXIT} specifies the range that injections
// should be carried out on (should be a subset of the above)
// and only works with FILTER_INSTRUCTIONS turned on
#define L4SYS_FILTER_ENTRY 0x200002ba
#define L4SYS_FILTER_EXIT 0x20000444
#define L4SYS_FILTER_ENTRY L4SYS_inj_start
#define L4SYS_FILTER_EXIT L4SYS_inj_end
#define L4SYS_BREAK_BLINK 0xf004b800
#define L4SYS_BREAK_LONGJMP 0xf004c88e
#define L4SYS_BREAK_BLINK 0x0
#define L4SYS_BREAK_LONGJMP 0x0
#define L4SYS_BREAK_EXIT 0x0
// select instruction filtering
// XXX: this should be always on and the code should be
@ -31,12 +37,12 @@
#define L4SYS_FILTER_INSTRUCTIONS 1
// kernel: 2377547, userland: 79405472
#define L4SYS_NUMINSTR 27025
#define L4SYS_TOTINSTR 189122
#define L4SYS_NUMINSTR 16
#define L4SYS_TOTINSTR 58401
#define L4SYS_BOCHS_IPS 5000000
// several file names used
#define L4SYS_STATE_FOLDER "l4sys.state"
#define L4SYS_STATE_FOLDER "l4sys.state"
#define L4SYS_INSTRUCTION_LIST "ip.list"
#define L4SYS_ALU_INSTRUCTIONS "alu.list"
#define L4SYS_CORRECT_OUTPUT "golden.out"