Lunatik
Lunatik is a framework for scripting the Linux kernel with Lua.
Install / Use
/learn @luainkernel/LunatikREADME
Lunatik
Lunatik is a framework for scripting the Linux kernel with Lua. It is composed by the Lua interpreter modified to run in the kernel; a device driver (written in Lua =)) and a command line tool to load and run scripts and manage runtime environments from the user space; a C API to load and run scripts and manage runtime environments from the kernel; and Lua APIs for binding kernel facilities to Lua scripts.
Note: Lunatik supports Linux Kernel versions 5.15 and later
Feel free to join us on Matrix.
Here is an example of a character device driver written in Lua using Lunatik to generate random ASCII printable characters:
-- /lib/modules/lua/passwd.lua
--
-- implements /dev/passwd for generate passwords
-- usage: $ sudo lunatik run passwd
-- $ head -c <width> /dev/passwd
local device = require("device")
local linux = require("linux")
local s = linux.stat
local driver = {name = "passwd", mode = s.IRUGO}
function driver:read() -- read(2) callback
-- generate random ASCII printable characters
return string.char(linux.random(32, 126))
end
-- creates a new character device
device.new(driver)
Setup
Install dependencies (here for Debian/Ubuntu, to be adapted to one's distribution):
sudo apt install git build-essential lua5.4 dwarves clang llvm libelf-dev linux-headers-$(uname -r) linux-tools-common linux-tools-$(uname -r) pkg-config libpcap-dev m4
Install dependencies (here for Arch Linux):
sudo pacman -S git lua clang llvm m4 libpcap pkg-config build2 linux-tools linux-headers
The lua-readline package is optional. When installed, the REPL gains line editing and command history:
sudo apt install lua-readline # Debian/Ubuntu
Compile and install lunatik:
LUNATIK_DIR=~/lunatik # to be adapted
mkdir "${LUNATIK_DIR}" ; cd "${LUNATIK_DIR}"
git clone --depth 1 --recurse-submodules https://github.com/luainkernel/lunatik.git
cd lunatik
make
sudo make install
Once done, the debian_kernel_postinst_lunatik.sh script from tools/ may be copied into
/etc/kernel/postinst.d/: this ensures lunatik (and also the xdp needed libs) will get
compiled on kernel upgrade.
OpenWRT
Install Lunatik from our package feed.
Usage
sudo lunatik # execute Lunatik REPL
Lunatik 4.2 Copyright (C) 2023-2026 Ring Zero Desenvolvimento de Software LTDA.
> return 42 -- execute this line in the kernel
42
lunatik
usage: lunatik [load|unload|reload|status|test|list] [run|spawn|stop <script>]
load: load Lunatik kernel modulesunload: unload Lunatik kernel modulesreload: reload Lunatik kernel modulesstatus: show which Lunatik kernel modules are currently loadedtest [suite]: run installed test suites (see Testing)list: show which runtime environments are currently runningrun [softirq]: create a new runtime environment to run the script/lib/modules/lua/<script>.lua; passsoftirqfor hooks that fire in atomic context (netfilter, XDP)spawn: create a new runtime environment and spawn a thread to run the script/lib/modules/lua/<script>.luastop: stop the runtime environment created to run the script<script>default: start a REPL (Read–Eval–Print Loop)
Testing
Install and run the test suites:
sudo make tests_install
sudo lunatik test # run all suites
sudo lunatik test thread # run a specific suite (monitor, thread, runtime)
Lua Version
Lunatik 4.2 is based on Lua 5.5 adapted to run in the kernel.
Floating-point numbers
Lunatik does not support floating-point arithmetic,
thus it does not support __div nor __pow
metamethods
and the type number has only the subtype integer.
Lua API
Lunatik does not support the os library,
floating-point arithmetic (__div, __pow), or debug.debug.
The math library is present but all floating-point functions are absent —
only integer operations are supported.
The io library is supported with the
following limitations: there are no default streams (io.stdin, io.stdout, io.stderr),
no default input/output (io.read, io.write, io.input, io.output), no process pipes
(io.popen), no temporary files (io.tmpfile), and no buffering control (file:setvbuf).
The available functions are io.open, io.lines, io.type, and the file handle methods
read, write, lines, flush, seek, and close.
On failure, error messages always read "I/O error" regardless of the underlying errno.
Lunatik modifies the following identifiers:
- _VERSION: is defined as
"Lua 5.5-kernel". - collectgarbage("count"): returns the total memory in use by Lua in bytes, instead of Kbytes.
- package.path: is defined as
"/lib/modules/lua/?.lua;/lib/modules/lua/?/init.lua". - require: only supports built-in or already linked C modules, that is, Lunatik cannot load kernel modules dynamically.
Lunatik Lua APIs
Lua APIs are documented with LDoc and can be browsed at luainkernel.github.io/lunatik.
The table below lists the available kernel Lua modules:
| Module | Description |
|--------|-------------|
| linux | Kernel utilities: schedule, time, random, stat flags |
| thread | Kernel threads: spawn, stop, shouldstop |
| socket | Kernel sockets: TCP, UDP, AF_PACKET, AF_UNIX |
| data | Raw memory buffer for binary data read/write |
| device | Character device drivers |
| rcu | RCU-protected shared hash table |
| netfilter | Netfilter hooks: register packet processing callbacks |
| skb | Socket buffer (sk_buff): inspect and modify packets |
| xdp | XDP (eXpress Data Path) hooks |
| crypto | Kernel crypto API: hash, cipher, AEAD, RNG, compression |
| hid | HID device drivers |
| probe | Kernel probes (kprobe / tracepoint) |
| fib | FIB routing table lookup |
| fifo | Kernel FIFO queues |
| signal | POSIX signal management |
| byteorder | Network byte order conversions |
| darken | AES-256-CTR encrypted script execution |
| lighten | Lua interface for running encrypted scripts via darken |
| notifier | Kernel notifier chain registration |
| lunatik.runner | Run, spawn, and stop scripts from within Lua |
| net | Networking helpers |
| mailbox | Asynchronous inter-runtime messaging |
Lunatik C API
The C API allows kernel modules to create and manage Lunatik runtime environments, define new object classes, and expose kernel facilities to Lua scripts. See doc/capi.md for the full reference.
Examples
spyglass
spyglass
is a kernel script that implements a keylogger inspired by the
spy kernel module.
This kernel script logs the keysym of the pressed keys in a device (/dev/spyglass).
If the keysym is a printable character, spyglass logs the keysym itself;
otherwise, it logs a mnemonic of the ASCII code, (e.g., <del> stands for 127).
Usage
sudo make examples_install # installs examples
sudo lunatik run examples/spyglass # runs spyglass
sudo tail -f /dev/spyglass # prints the key log
sudo sh -c "echo 'enable=false' > /dev/spyglass" # disable the key logging
sudo sh -c "echo 'enable=true' > /dev/spyglass" # enable the key logging
sudo sh -c "echo 'net=127.0.0.1:1337' > /dev/spyglass" # enable network support
nc -lu 127.0.0.1 1337 & # listen to UDP 127.0.0.1:1337
sudo tail -f /dev/spyglass # sends the key log through the network
keylocker
keylocker
is a kernel script that implements
Konami Code
for locking and unlocking the console keyboard.
When the user types ↑ ↑ ↓ ↓ ← → ← → LCTRL LALT,
the keyboard will be locked; that is, the system will stop processing any key pressed
until the user types the same key sequence again.
Usage
sudo make examples_install # installs examples
sudo lunatik run examples/keylocker # runs keylocker
<↑> <↑> <↓> <↓> <←> <→> <←> <→> <LCTRL> <LALT> # locks keyboard
<↑> <↑> <↓> <↓> <←> <→> <←> <→> <LCTRL> <LALT> # unlocks keyboard
tap
tap
is a kernel script that implements a sniffer using AF_PACKET socket.
It prints destination and source MAC addresses followed by Ethernet type and the frame size.
Usage
sudo make examples_install # installs examples
sudo lunatik run examples/tap # runs tap
cat /dev/tap
shared
shared is a kernel script that implements an in-memory key-value store using rcu, data, socket and thread.
Usage
sudo make examples_install # installs examples
sudo lunatik spawn examples/shared # spawns shared
nc 127.0.0.1 90 # connects to shared
foo=bar # assigns "bar" to foo
foo # retrieves foo
bar
^C # finishes the connection
echod
echod is an echo server im
