[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;
};
|