Software-implemented fault injection (SWIFI) is an established method to emulate hardware faults in computer systems. Existing approaches either extend the operating system by special drivers, modify the runtime environment, or change the application under test.
In cooperation with Fujitsu Technology Solutions in Paderborn, we worked on the realization of a novel fault injection concept based on EFI firmware technology. Our approach extends the firmware of these systems in order to a) make fault injection completely transparent to the operating system, and to b) support a larger variety of fault types. No modifications to the operating system or the application code are needed.
Due to technical limitations of the EFI implementations available today, the project has been suspended. Our final software stack is freely available for further research.
You can download compiled packages here. Be aware that the architecture must match your (U)EFI firmware architecture.
Extract the following files from the binary distribution into a folder on the EFI system partition:
Depending on the operating system you need the following files accessible from within the operating system:
EFInject is prepared to perform injections several times. The package provides a helper script and application to run a specified number of injection cycles.
First of all you need to configure the injection itself. The configuration method is described in a separate section below. After configuring the driver you can set the number of injection cycles using the helper application:
InjectReportApp setcycles [count]
To integrate with EFInject with your system you have to modify both the
loadefinject.nsh and your
exit command with whatever is necessary to boot the operating system
under test. Then modify your
startup.nsh so that you change the directory
to the one where the EFInject file live and that
loadefinject.nsh is called
afterwards. Finally make sure that the default boot option is the internal EFI
shell which calls the
Modify the operating so that it starts the appropriate tick script with root/Administrator privileges during boot.
To configure EFInject, launch the EFInject helper application from the EFI Shell in the following way:
InjectReportApp configure [configuration string]
The configuration string consists of four parameters delimited by semicolons:
the trigger mechanism, currently
the trigger parameters, which is the number of ticks until the first or between the injections, depending on the selected trigger
the injection mechanism, currently
the injection parameter
for the reset injector: the parameter is ignored
for the memory injector: three hexadecimal values separated by commas: the virtual memory address for the injection, an OR- and an XOR-parameter; the injection semantic is
*memoryLocation = (*memoryLocation | orParameter) ^ xorParameter
for the register injector: three values, also using hexadecimal numbers: the uppercase name of a general purpose register, and the OR- and XOR-parameter already described for the memory injector
Both injectors always work with native-sized memory words, i.e. with DWORDs on IA32 and with QWORDs on X64.
The OR-XOR-semantics allow for four different actions for each bit in the register/memory location:
- or=0, xor=0: no action
- or=0, xor=1: flip bit
- or=1, xor=0: set to 1
- or=1, xor=1: set to 0
At this time the supported registers are:
- for IA32: EFLAGS 2, EDI, ESI, EBP, EBX, EDX, ECX, EAX
- for X64: RFLAGS 3, RAX, RBX, RCX, RDX, RDI, RSI, R8, R9, R10, R11, R12, R13, R14, R15, RBP
- ^ There is a third injection method called
nopwhich does nothing and ignores its configuration parameter but can be used to test the infrastructure. No crashes should occur when using the
- ^ Not all flags of EFLAGS are supported: VM, RF, VIP and VIF are ignored.
- ^ The EFLAGS restrictions apply and the upper 32 bit of RFLAGS are ignored.
- flips the lower four bits of the general-purpose EAX register on every third tick (IA32)
- sets the least-significant bit of RAX
- flips the least-significant bit of the memory cell at 0x000000f0
If something does not work, try the following steps:
oneshot;1;nop; should always be valid regardless of the
underlying platform. Therefore the following commands should always work and
result in a running driver:
InjectReportApp.efi configure oneshot;1;nop; load InjectReportDxe.efi
To test the driver itself, you can issue commands from the EFI shell. As the
driver uses the variable interface to communicate with the shell and operating
systems, you can use the
dmpstore tool to run some tests. The following
command should print some data showing a UTF16-encoded
If you run Linux as an operating system after loading the driver, the equivalent to the command above would be: (run as root)
In the commands above, you can replace the verb
perform an immediate injection (independent of any trigger) or
call the trigger once.