EFInject

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.

Download

You can download compiled packages here. Be aware that the architecture must match your (U)EFI firmware architecture.

Installation

Extract the following files from the binary distribution into a folder on the EFI system partition:

  • InjectReportApp.efi
  • InjectReportDxe.efi
  • loadefinject.nsh

Depending on the operating system you need the following files accessible from within the operating system:

Windows:
tick.cmd and efiwin.exe
Linux:
tick.sh

Injection cycles

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 startup.nsh. In loadefinject.nsh replace the 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 startup.nsh script.

Modify the operating so that it starts the appropriate tick script with root/Administrator privileges during boot.

Configuration

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 oneshot or interval

  • 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 reset, memory or register 1

  • 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
1.
^ There is a third injection method called nop which does nothing and ignores its configuration parameter but can be used to test the infrastructure. No crashes should occur when using the nop injector.
2.
^ Not all flags of EFLAGS are supported: VM, RF, VIP and VIF are ignored.
3.
^ The EFLAGS restrictions apply and the upper 32 bit of RFLAGS are ignored.

Configuration Examples

interval;3;register;EAX,00000000,0000000F
flips the lower four bits of the general-purpose EAX register on every third tick (IA32)
oneshot;4;register;RAX,1,0
sets the least-significant bit of RAX
interval;3;memory;F0,0,1
flips the least-significant bit of the memory cell at 0x000000f0

Troubleshooting

If something does not work, try the following steps:

The configuration 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 Callback works! string:

dmpstore Test

If you run Linux as an operating system after loading the driver, the equivalent to the command above would be: (run as root)

hd /sys/firmware/efi/vars/Test-8b1cd116-7f14-4594-8474-edbebda318ce/data

In the commands above, you can replace the verb Test with Inject to perform an immediate injection (independent of any trigger) or Tick to call the trigger once.