A research prototype of a post-boot loadable kernel module that, once activated at
runtime, denies any new means of introducing or modifying kernel-mode executable code on
a stock Debian x86-64 kernel with Secure Boot active. Where Secure Boot protects
the pre-insertion window, klock protects everything after — and then seals itself in
so it can't be unloaded or bypassed.
Research prototype — runs in QEMU first, never bare-metal. Charter (authoritative, French):
cahier_des_charges_verrouillage_kernel_runtime.md. Engineering invariants:.github/copilot-instructions.md. Sibling project — CoKernel is the offensive counterpart (stealth in-kernel execution);klockis the lockdown that aims to deny it.
flowchart TD
BOOT["Secure Boot — protects up to our insertion (not our job)"] --> INS["insmod klock.ko (signed, MOK-enrolled)"]
INS --> LOCK["transition: unlocked → locked\n(/sys/kernel/klock/ control plane)"]
LOCK --> HOOKS["install hooks (ftrace IPMODIFY — kprobes are blocked under Secure Boot)"]
subgraph CATS["5 categories of 'new kernel-mode code' to deny once locked"]
A["A · module loading (finit_module / init_module)"]
B["B · kprobes / ftrace registration by others"]
C["C · BPF JIT / unprivileged code paths"]
D["D · text_poke / patching primitives"]
E["E · /dev/mem, kexec, debug write paths"]
end
HOOKS --> CATS
LOCK --> SEAL["seal: pin our own refcount · hook unregister_* / disarm_all_kprobes · block text_poke callers\n→ klock can't be removed or disarmed"]
CATS & SEAL --> RES["result: post-boot kernel text is frozen"]
Scaffolding. The module builds, loads, exposes the /sys/kernel/klock/ control plane,
and transitions into the "locked" state — but the per-category hooks aren't implemented
yet; they're being filled in incrementally per docs/roadmap.md. What's
real today: the build (Kbuild, x86_64 + arm64), the QEMU/OVMF/MOK test harness
(make setup / make smoke), the sysfs control plane, the lock-state machine, and the
allowlist / canary / critical-region plumbing. See docs/architecture.md
and docs/hooks-table.md.
Debian 12 or 13 with the following packages:
sudo apt install \
build-essential linux-headers-$(uname -r) linux-kbuild-$(uname -r) \
qemu-system-x86 qemu-utils ovmf python3-virt-firmware \
genisoimage openssl wget openssh-clientKVM access (/dev/kvm readable) is strongly recommended; TCG fallback
works but is an order of magnitude slower.
# 1. One-shot: generate signing keys, build OVMF_VARS with MOK enrolled,
# download Debian Trixie cloud image, build cloud-init seed.iso.
make setup
# 2. End-to-end smoke test (builds, signs, boots, runs harness, collects result).
make smokemake smoke is the canonical development loop. It returns 0 iff every
test in tests/harness/run_tests.sh passes.
See §3 of .github/copilot-instructions.md for a commented repository map.
- Stock Debian kernel, no custom build, no special
CONFIG_*. - Post-boot activation: we do not protect the window before our own insertion; that is Secure Boot's job.
- Ftrace IPMODIFY is the primary hook mechanism, not kprobes — the lockdown LSM blocks new kprobe registration under Secure Boot.
- Seal after locking: we pin our own refcount, hook
unregister_*/disarm_all_kprobes, and blocktext_pokecallers. - Everything runs in QEMU first. No bare-metal testing.
GPL-2.0 — Linux kernel module; research prototype.
Part of my work — more at zz0r0.fr.