Lunatik, lua inside kernel boundary
What?
Lunatik is a framework for scripting the Linux kernel using Lua. It allows developers to write kernel-resident logic in a high-level language, while still interacting directly with kernel facilities such as networking, devices, timing, and system state.
At a high level, Lunatik consists of:
- A modified Lua interpreter that runs inside the Linux kernel
- A kernel-space C API to manage Lua runtimes and execute scripts
- Lua-based device driver layer
- User-space CLI tool (lunatik) to load, run, and manage kernel Lua environments
- Lua bindings that expose kernel facilities to Lua scripts
This architecture allows Lua to be used as a control and orchestration language inside the kernel, enabling rapid prototyping, instrumentation, and kernel-adjacent logic without writing everything in C.
Why Script the Kernel?
Traditionally, Linux kernel development is done entirely in C, which offers maximum control and performance, but at the cost of:
- Long development and iteration cycles
- Higher risk of memory safety bugs
- Lower-level abstractions for expressing logic
Lunatik explores a different tradeoff: keeping performance-critical components in C, while enabling higher-level logic to be expressed in Lua. This makes Lunatik particularly useful for:
- Prototyping kernel logic
- Writing dynamic device behavior
- Experimentation and research
Notable contributions
I’ve been an active contributor to Lunatik, focusing on performance, API correctness, and low-level networking support. Some of my notable contributions include:
Improving Method Dispatch Performance
Lunatik previously used index-based (__index) lookups for method dispatch, which introduced extra allocations and overhead in hot paths. I redesigned this mechanism to eagerly wrap class methods at initialization, eliminating repeated index lookups during runtime. This:
- Reduced dynamic allocations in hot paths
- Simplified the method call path
- Improved overall dispatch performance
This change significantly reduced per-call overhead in performance-sensitive code paths. PR: #410
Enforcing Correct Raw Socket Binding Semantics
To prevent subtle API misuse, I enforced explicit pairing of (protocol, ifindex) when binding raw sockets. This change:
- Prevents ambiguous or incorrect socket binding
- Makes API usage more explicit and self-documenting
- Improves correctness for low-level packet handling
PR: #378