KernInst
structure
- kerninstd: user-level daemon
- allocate the patch area heap
- parse the kernel’s runtime symbol table
- obtain permission to write to any portion of the kernel’s address space
- call /dev/kerninst to allocate kernel memory to code patches
- use kernel machine code to build a control flow graph
- /dev/kerninst: runtime-loaded KernInst driver
- communicate with kerninstd via file operations
- installed on-the-fly
- run-time allocated heaps:
- patch area heap: dynamically generated code. it is mapped by mmap, so it is accessible to kernel and kerninstd
- timers and counters heap: used when instrumentation code contains performance gathering annotations
- Overwrting a single instruction is safe than multiple-instruction splicing
- beacuse a thread execute a mix of the pre-slice and post-slice sequences
Structural Analysis
- Runtime symbol table is parsed to determine the in-memory start of all kernel functions
- Each function’s machine code is then read from memory and parsed into basic blocks
Use free registers at instrumentation points
- for jumping/executing to dynamically inserted code
- run interprocedural live register analysis algorithm
Code Splicing
- inserting runtime generated code before a desired kernel code location (the instrumentation point)
- Kerninstd splices by overwriting the instrumentation point instruction with a branch to patch code, which includes:
- dynamically generated code
- original overwitten instruction
- jump back to the instruction stream after original instrumentation point
Springboards
Reviews
- Symbol table
- Hooking
- Control flow graph
- Just-in-time compilation
- Why Solaris?
- Solaris kernel is more clean
- Solaris could track the source of a trap
- Why not let the compiler to patch?