554a58757e
Closes the gap between 'detect() compiles and passes unit tests' and
'exploit() actually works on a real vulnerable kernel'. One-time
setup + one command per module to verify against a known-vulnerable
guest, with results emitted as JSON verification records.
Files:
setup.sh — one-shot bootstrap. Installs Vagrant via brew if
missing, installs vagrant-parallels plugin, pre-
downloads 5 base boxes (~5 GB):
generic/ubuntu1804 (4.15.0)
generic/ubuntu2004 (5.4.0 + HWE)
generic/ubuntu2204 (5.15.0 + HWE)
generic/debian11 (5.10.0)
generic/debian12 (6.1.0)
Idempotent; can pass --boxes subset.
Vagrantfile — single parameterized config driven by SKK_VM_*
env vars. Provisioners: build-deps install,
kernel pin (apt + snapshot.debian.org fallback),
build-and-verify (kept run='never' so verify.sh
invokes explicitly after reboot if pin'd).
targets.yaml — module → (box, kernel_pkg, kernel_version,
expect_detect, notes) mapping for all 26 modules.
3 marked manual: true (vmwgfx needs VMware guest;
dirtydecrypt + fragnesia need Linux 7.0 not yet
shipping as distro kernel).
verify.sh — entrypoint. 'verify.sh <module>' provisions if
needed, pins kernel + reboots if needed, runs
'skeletonkey --explain --active' inside the VM,
parses VERDICT, compares to expect_detect, emits
JSON verification record. --list shows the full
target matrix. --keep / --destroy lifecycle flags.
README.md — workflow + extending the targets table.
Design notes:
- Pure bash + awk targets.yaml parsing — no PyYAML dep (macOS Python
is PEP-668 'externally managed' and refuses pip --user installs).
- Sources of vulnerable kernel packages: stock distro kernels where
they're below the fix backport, otherwise pinned via apt with
snapshot.debian.org as last-resort fallback (the Debian apt
snapshot archive is the canonical source for historical kernel .deb
packages).
- Repo mounted at /vagrant via rsync (not 9p — vagrant-parallels'
9p is finicky on macOS Sequoia per the plugin issue tracker).
- VM lifecycle defaults to suspend-after-verify so the next run
resumes in ~5s instead of cold-booting.
- kernel pin reboots are handled by checking 'uname -r' after the
pin provisioner and triggering 'vagrant reload' if mismatched.
Verification records (JSON on stdout per run) are intended to feed a
per-module verified_on[] table in a follow-up commit — that's the
'permanent trust artifact' angle from the earlier roadmap discussion.
Smoke tests (no VM actually spun up):
- 'verify.sh --list': renders the 26-module matrix correctly.
- 'verify.sh nf_tables': dispatches to generic/ubuntu2204 + kernel
5.15.0-43 + expect=VULNERABLE; fails cleanly at 'vagrant: command
not found' (expected — user runs setup.sh first).
- 'verify.sh vmwgfx': errors with 'is marked manual: true' + note.
.gitignore: tools/verify-vm/{logs,.vagrant}/ excluded.
Usage:
./tools/verify-vm/setup.sh # one time, ~5 min
./tools/verify-vm/verify.sh nf_tables # ~5 min first run, ~1 min after
./tools/verify-vm/verify.sh --list # show all targets
90 lines
3.3 KiB
Ruby
90 lines
3.3 KiB
Ruby
# -*- mode: ruby -*-
|
|
# vi: set ft=ruby :
|
|
#
|
|
# tools/verify-vm/Vagrantfile — parameterized verifier VM.
|
|
#
|
|
# Driven by env vars set by tools/verify-vm/verify.sh:
|
|
#
|
|
# SKK_VM_BOX generic/<box> name (e.g. generic/debian11)
|
|
# SKK_VM_KERNEL_PKG optional apt package for the vulnerable kernel
|
|
# (e.g. linux-image-5.13.0-19-generic). Empty = use stock.
|
|
# SKK_VM_KERNEL_VERSION expected kernel version after install
|
|
# SKK_VM_HOSTNAME hostname for this VM (used in vagrant box name)
|
|
#
|
|
# The Vagrantfile mounts the repo root at /vagrant (Vagrant default) so the
|
|
# in-VM `make` builds against your live source — no rebuild loop.
|
|
|
|
require "yaml"
|
|
|
|
REPO_ROOT = File.expand_path("../..", __dir__)
|
|
|
|
box = ENV["SKK_VM_BOX"] || "generic/debian12"
|
|
pkg = ENV["SKK_VM_KERNEL_PKG"] || ""
|
|
kver = ENV["SKK_VM_KERNEL_VERSION"] || ""
|
|
host = ENV["SKK_VM_HOSTNAME"] || "skk-verify"
|
|
|
|
Vagrant.configure("2") do |c|
|
|
c.vm.box = box
|
|
c.vm.hostname = host
|
|
|
|
c.vm.synced_folder REPO_ROOT, "/vagrant",
|
|
type: "rsync", rsync__exclude: ["build/", ".git/", "*.o", "skeletonkey-test*"]
|
|
|
|
c.vm.provider "parallels" do |p|
|
|
p.memory = 2048
|
|
p.cpus = 2
|
|
p.name = host
|
|
# Headless: don't pop a Parallels GUI window for every verify run.
|
|
p.update_guest_tools = true
|
|
end
|
|
|
|
# 1. Always install build deps + sudo (needed for module verification).
|
|
c.vm.provision "shell", inline: <<-SHELL
|
|
set -e
|
|
if command -v apt-get >/dev/null 2>&1; then
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
apt-get update -qq
|
|
apt-get install -y -qq build-essential libglib2.0-dev pkg-config sudo curl ca-certificates
|
|
elif command -v dnf >/dev/null 2>&1; then
|
|
dnf install -y -q gcc make glib2-devel pkgconfig sudo curl
|
|
fi
|
|
SHELL
|
|
|
|
# 2. Pin target kernel if requested. Reboot needed afterward.
|
|
if !pkg.empty?
|
|
c.vm.provision "shell", name: "pin-kernel-#{pkg}", inline: <<-SHELL
|
|
set -e
|
|
if dpkg-query -W -f='${Status}' #{pkg} 2>/dev/null | grep -q 'install ok installed'; then
|
|
echo "[=] #{pkg} already installed"
|
|
else
|
|
echo "[+] installing #{pkg} (kernel target #{kver})"
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
apt-get install -y -qq #{pkg} || {
|
|
echo "[-] #{pkg} unavailable in apt; trying snapshot.debian.org" >&2
|
|
echo "deb [check-valid-until=no] http://snapshot.debian.org/archive/debian/20230101T000000Z bookworm main" \
|
|
>> /etc/apt/sources.list.d/snapshot.list
|
|
apt-get update -qq -o Acquire::Check-Valid-Until=false
|
|
apt-get install -y -qq --allow-downgrades #{pkg}
|
|
}
|
|
echo "[i] kernel #{pkg} installed; reboot via 'vagrant reload'"
|
|
fi
|
|
SHELL
|
|
end
|
|
|
|
# 3. Build SKELETONKEY in-VM and run --explain --active for the target module.
|
|
# SKK_MODULE is set by verify.sh on the second-pass `vagrant provision` call
|
|
# (post-reboot if kernel was pinned).
|
|
c.vm.provision "shell", name: "build-and-verify", run: "never", inline: <<-SHELL
|
|
set -e
|
|
cd /vagrant
|
|
echo "[*] kernel: $(uname -r)"
|
|
echo "[*] building skeletonkey..."
|
|
make clean >/dev/null 2>&1 || true
|
|
make 2>&1 | tail -3
|
|
echo
|
|
echo "[*] running: skeletonkey --explain ${SKK_MODULE} --active"
|
|
echo
|
|
./skeletonkey --explain "${SKK_MODULE}" --active 2>&1 || true
|
|
SHELL
|
|
end
|