[Fault-injection-developer] [RFC] revised model for core/interceptor interaction
Status: Alpha
Brought to you by:
rustyl
From: Rusty L. <ru...@li...> - 2002-12-17 23:55:23
|
Ok, here is something to chew on. When I reviewed the feedback on my changes to fi_core.c, I realized that part of my problem with having the core code 'execute' the trigger was that too many assumptions were made about the design of the interceptor (in our case pf*.c). I think that this model for fault injection can be made to do more then just corrupt some data. For example, I can envision a trigger that results in a code segment being executed just before a specific address is execute if a set of filtering criteria is first meet. What if we: 1. (as Louis hinted) narrow our notion of an interceptor to strictly be a component that knows how to divert a thread of execution to the core. ** An interceptor knows how to intercept type of condition ** ** Possible Examples: - MMIO Given a physical address, a MMIO interceptor can intercept the specific address before the caller reading/writing to the address returns from a read/write operation. - PIO Given an io port, a PIO interceptor can intercept the data being read/written from/to that port. - Executable Given a kernel mapped address, a EXEC interceptor can intercept just before the location is executed. 2. introduce the concept of an 'injector' that only knows how to inject a given fault. (It could be that a block of code implements both interfaces, but as far as the core is concerned, they are two different components.) ** An injector knows how to inject a specific type of fault ** ** Possible Examples: - MMIO Given a physical address, a MMIO injector can write to that address without the owner of that mmaped io realizing it. (Given the nature of how mmio is implemented in the kernel, this injector will probably have to be implemented by the same code as the injector.) - Executable Given a kernel mapped address, a EXEC injector can cause an arbitrary block of code to be executed just before the kernel address. I created the text below as a new entry for Documentation/fault_injection.txt. It is still fairly empty, but I attempted to further explain the notion of injections and interceptors and how they interact with the core. I also took a stab at how the datatypes, but I have not yet implemented any of this, so there could be some fundamental problems with the model. -rusty ******************************************************************************* * Fault Injection ******************************************************************************* Original Author: Rusty Lynch <ru...@li...> Contributors: Fault injection is composed of: 1. core functionality (kernel/fi_core.c) a. handles all user space interaction b. contains core logic for handling faults 2. interceptors a. enables core to intercept various types of events b. the core knows how to use specific types of interceptors, but does not know how the interceptors are implemented 3. injectors a. enables core to inject specific types of faults b. the core knows how to use specific types of injectors, but does not know how the injectors are implemented User space interaction ---------------------- Interceptor / Injector interaction with the fault injection core ---------------------------------------------------------------- Registration: ------ fi_register_interceptor() ------------------------ | core | <----------------------------------- | interceptor (MMIO type)| ------ ------------------------ ------ fi_register_injector() --------------------- | core | <----------------------------------- | injector (MMIO type)| ------ --------------------- Configuration: Add the following MMIO trigger ------ User space --------------------------------------> | core | ------ ** Core searches for and finds the previously registered MMIO interceptor ** ------ interceptor->arm(physical_address) ------------------------ | core | ------------------------------------> | interceptor (MMIO type)| ------ ------------------------ Interceptor is triggered: ------ fi_event_handler(i) ------------------------ | core | <------------------------------ | interceptor (MMIO type)| ------ ------------------------ ** Inside the fi_event_handler(): -- core determines what action is to be taken, and decides to replace the data that is about to be returned by the caller of the MMIO data -- core searches for and finds an appropriate injector ------ injector->inject() --------------------- | core | ----------------------> | injector (MMIO type)| ------ --------------------- ------ ok ------------------------ | core | ------------------------------> | interceptor (MMIO type)| ------ ------------------------ Deactivating specific interceptors: Disable the following interceptor ------ User space --------------------------------------> | core | ------ ------ interceptor->set_status(FI_INTERCEPTOR_STATUS_DISABLED) ------------- | core | -----------------------------------------------------> | interceptor | ------ ------------- Removing a configuration: Remove the following trigger ------ User space --------------------------------------> | core | ------ ------ interceptor->disarm() ------------------------ | core | ------ ------------------------------> | interceptor (MMIO type)| ------ ------------------------ /* Core */ extern int fi_register_interceptor(struct fi_interceptor *); extern int fi_unregister_interceptor(struct fi_interceptor *); extern int fi_register_injector(struct fi_injector *); extern int fi_unregister_injector(struct fi_injector *); extern int fi_event_handler(struct pt_regs *, struct fi_interceptor *, void *); /* Interceptors */ typedef enum { INTERCEPTOR_STATUS_UNKNOWN=0, INTERCEPTOR_STATUS_ENABLED=1, INTERCEPTOR_STATUS_DISABLED=2 } fi_interceptor_status_t; typedef enum { FI_INTERCEPTOR_TYPE_UNKNOWN=0, FI_INTERCEPTOR_TYPE_MMIO=1 } fi_interceptor_type_t; struct fi_interceptor { interceptor_type_t type; interceptor_status_t get_status(void); int set_status(interceptor_status_t status); int arm(void *data); int disarm(void *data); kobject kobj; }; /* Injectors */ typedef enum { FI_INJECTOR_TYPE_UNKNOWN=0, FI_INJECTOR_TYPE_MMIO=1 } fi_injector_type_t; struct fi_injector { fi_injector_type_t type; int inject(struct pt_regs * regs, void *data); kobject kobj; }; |