Kernel Surface Ledger ksl

Every other tool tells you what kernel attack surface is exposed. This one tells you who is responsible for it, what nothing is using, and the shortest way out.

source: bundled demo scan
kernel 6.8.0-45-genericarch x86_64distro Ubuntu 24.04.1 LTScollected 2026-08-22 15:04:11Ztrace strace / 60sprivilege rootksl 0.1.0

total surface weight

149

every element present, reachable or not

reachable surface weight

106after plan 43.5

reachable by an unprivileged local user

reachable CVEs

19after plan 9

CVE mass behind reachable surface

orphan ratio

49.1%

reachable weight touched by nothing

00 / interrogate

Ask this report

The narration layer, live and grounded: it answers from the loaded JSON, cites element and workload ids, and names what the data cannot tell you rather than guessing.

Grounded in the loaded report only. If the answer is not in the data, it says what is missing instead of inventing it.

01 / attribution

Surface Debt Ledger

Dangerous kernel surface is a jointly held liability across every live workload on the host. Each row is one workload's share: its debt, its marginal contribution, the surface it alone keeps open, and the CVE mass that surface exposes. Expand a row for the causal narration. The last row is the point.

Surface debt ledger: kernel attack surface attributed to each live workload
expandsole owner
dockerddocker.service
unprivileged user namespacesio_uring_setupkeyctl
17.259.509yes · 1
libvirtdlibvirtd.service
/dev/kvm
771yes · 1
nginxnginx.service
io_uring_setup
4.5003no
udisksdudisks2.service
usb-storage
4.504.501yes · 1
sshdssh.service
keyctl
3.2502no
orphaned

reachable by any local user, touched by nothing 8 elements

527

02 / free hardening

Orphaned surface

Present, reachable by any unprivileged local user, and used by nothing during the observation window. Removing it is provably zero-impact — nothing touches it.

52weighted units of unprivileged-reachable surface

7CVEs neutralizable at zero cost

bluetooth

6

mod.bluetooth

modulebluetoothbluetooth-parsing

gate: loaded: bluetooth

dccp

7

mod.dccp

modulenetdccp-uafnet-legacy-proto

gate: not loaded but autoloadable via modules.dep (dccp)

cramfs / freevxfs / jffs2 / hfsplus / udf

5

mod.legacy_fs

modulefsfs-image-parsing

gate: not loaded but autoloadable via modules.dep (cramfs, freevxfs, hfsplus, jffs2, udf)

n_hdlc

5.5

mod.n_hdlc

modulettytty-ldisc-lpe

gate: not loaded but autoloadable via modules.dep (n_hdlc)

rds

6.5

mod.rds

modulenetnet-legacy-proto

gate: not loaded but autoloadable via modules.dep (rds)

tipc

6.5

mod.tipc

modulenetnet-legacy-protoremote-heap-overflow

gate: not loaded but autoloadable via modules.dep (tipc)

perf_event_open

7.5

sc.perf_event_open

syscallperfinfoleakperf-lpe

gate: kernel.perf_event_paranoid=2

userfaultfd

8

sc.userfaultfd

syscallmmheap-grooming-primitive

gate: vm.unprivileged_userfaultfd=1

03 / reachability, not mere presence

Three-tier gates

A CVE in a module that cannot be loaded is irrelevant; one reachable by any local user is critical. Every element passes present → reachable_unpriv → used, and module autoload turns 'not loaded' into one socket() call away.

22 / 22 elements
Every surface element with its three reachability tiers and gate reason
elementweightpresentreachable unprivusedgate reason / mitigations

CAP_SYS_ADMIN held by non-root workload

cap.sys_admin_unpriv

capabilitycapabilitiesnot presentcap-sys-admin-abuse
9present: noreachable by unprivileged user: noused by a live workload: nono non-root workload holds CAP_SYS_ADMIN
  • systemd NoNewPrivileges=yes and AmbientCapabilities= drop

kernel.dmesg_restrict = 0

cfg.dmesg_open

sysctlinfoleakreachable · usedinfoleak
4present: yesreachable by unprivileged user: yesused by a live workload: yeskernel.dmesg_restrict=0
  • sysctl kernel.dmesg_restrict=1

CONFIG_COMPAT (32-bit emulation)

cfg.kconfig_compat

kconfigcompatreachable · unusedcompat-ioctls
5.5present: yesreachable by unprivileged user: yesused by a live workload: nocompiled in

unrestricted module autoload

cfg.module_autoload

sysctlmodulesreachable · usedautoload-amplifier
7.5present: yesreachable by unprivileged user: yesused by a live workload: yeskernel.modules_disabled=0
  • sysctl kernel.modules_disabled=1 after boot
  • modprobe install <mod> /bin/false

kernel.kptr_restrict < 2

cfg.no_kptr_restrict

sysctlinfoleakreachable · usedinfoleak
5present: yesreachable by unprivileged user: yesused by a live workload: yeskernel.kptr_restrict=1
  • sysctl kernel.kptr_restrict=2

lockdown LSM inactive

cfg.no_lockdown

lsmlsmpresent · gatedkernel-integrity
6present: yesreachable by unprivileged user: noused by a live workload: noroot-only impact
  • boot with lockdown=confidentiality

/dev/kvm

dev.kvm

devnodekvmreachable · usedkvm-ioctl
7present: yesreachable by unprivileged user: yesused by a live workload: yesmode 0666 grants non-root
  • restrict group ownership to kvm

/dev/mem

dev.mem

devnodemmpresent · gatedphysical-memory-access
9present: yesreachable by unprivileged user: noused by a live workload: noblocked: mode 0640 denies non-root
  • boot lockdown=confidentiality
  • CONFIG_IO_STRICT_DEVMEM

bluetooth

mod.bluetooth

modulebluetoothreachable · unusedbluetooth-parsing
6present: yesreachable by unprivileged user: yesused by a live workload: noloaded: bluetooth
  • modprobe blacklist and install /bin/false

dccp

mod.dccp

modulenetreachable · unuseddccp-uafnet-legacy-proto
7present: yesreachable by unprivileged user: yesused by a live workload: nonot loaded but autoloadable via modules.dep (dccp)
  • modprobe blacklist and install /bin/false

firewire-core

mod.firewire_core

modulefirewirenot presentdma-physical-access
6present: noreachable by unprivileged user: noused by a live workload: nonot present on host
  • modprobe blacklist and install /bin/false

cramfs / freevxfs / jffs2 / hfsplus / udf

mod.legacy_fs

modulefsreachable · unusedfs-image-parsing
5present: yesreachable by unprivileged user: yesused by a live workload: nonot loaded but autoloadable via modules.dep (cramfs, freevxfs, hfsplus, jffs2, udf)
  • modprobe blacklist and install /bin/false

n_hdlc

mod.n_hdlc

modulettyreachable · unusedtty-ldisc-lpe
5.5present: yesreachable by unprivileged user: yesused by a live workload: nonot loaded but autoloadable via modules.dep (n_hdlc)
  • modprobe blacklist and install /bin/false

rds

mod.rds

modulenetreachable · unusednet-legacy-proto
6.5present: yesreachable by unprivileged user: yesused by a live workload: nonot loaded but autoloadable via modules.dep (rds)
  • modprobe blacklist and install /bin/false

tipc

mod.tipc

modulenetreachable · unusednet-legacy-protoremote-heap-overflow
6.5present: yesreachable by unprivileged user: yesused by a live workload: nonot loaded but autoloadable via modules.dep (tipc)
  • modprobe blacklist and install /bin/false

usb-storage

mod.usb_storage

moduleusbnot presentusb-parsing
4.5present: noreachable by unprivileged user: noused by a live workload: yesnot present on host
  • modprobe blacklist
  • USBGuard

unprivileged user namespaces

ns.userns_unpriv

namespacenamespacesreachable · usednetfilter-via-usernsuserns-lpe
9.5present: yesreachable by unprivileged user: yesused by a live workload: yeskernel.unprivileged_userns_clone=1
  • sysctl kernel.unprivileged_userns_clone=0
  • systemd RestrictNamespaces=

bpf (unprivileged)

sc.bpf_unpriv

syscallbpfpresent · gatedbpf-verifier
8.5present: yesreachable by unprivileged user: noused by a live workload: noblocked: kernel.unprivileged_bpf_disabled=1
  • sysctl kernel.unprivileged_bpf_disabled=1

io_uring_setup

sc.io_uring_setup

syscallio_uringreachable · usedio_uring-refcountio_uring-uaf
9present: yesreachable by unprivileged user: yesused by a live workload: yeskernel.io_uring_disabled=0
  • sysctl kernel.io_uring_disabled=2
  • seccomp deny io_uring_setup,io_uring_enter,io_uring_register

keyctl

sc.keyctl

syscallkeysreachable · usedkeyring-uafrefcount-overflow
6.5present: yesreachable by unprivileged user: yesused by a live workload: yes
  • seccomp deny keyctl,add_key,request_key

perf_event_open

sc.perf_event_open

syscallperfreachable · unusedinfoleakperf-lpe
7.5present: yesreachable by unprivileged user: yesused by a live workload: nokernel.perf_event_paranoid=2
  • sysctl kernel.perf_event_paranoid=3
  • seccomp deny perf_event_open

userfaultfd

sc.userfaultfd

syscallmmreachable · unusedheap-grooming-primitive
8present: yesreachable by unprivileged user: yesused by a live workload: novm.unprivileged_userfaultfd=1
  • sysctl vm.unprivileged_userfaultfd=0
  • seccomp deny userfaultfd

04 / counterfactual

Hardening plan

Hardening as weighted set cover: the changes that neutralize maximum reachable CVE mass per unit of estimated breakage. Not an unranked findings list — an ordered plan, each step shipping an artifact, a breakage prediction, a detection command and a revert.

cumulative CVE mass killed

5

7

12

13

16

5 steps → 16 reachable CVEs neutralized

  1. step 1blacklist_module

    bluetoothcramfsdccpfreevxfshfsplusjffs2n_hdlcrdstipcudf
    breakage: none5 CVEs killed36.5 weight

    what could break

    If a Bluetooth service (bluetoothd) is started, it would fail to load the bluetooth module

    detect it worked

    detection
    modprobe bluetooth 2>&1 | grep -i blacklisted

    revert

    revert
    sudo sed -i '/^blacklist bluetooth$/d; /^blacklist cramfs$/d; /^blacklist dccp$/d; /^blacklist freevxfs$/d; /^blacklist hfsplus$/d; /^blacklist jffs2$/d; /^blacklist n_hdlc$/d; /^blacklist rds$/d; /^blacklist tipc$/d; /^blacklist udf$/d' /etc/modprobe.d/blacklist.conf

    check this — did step 1 work?

    1. 1the check shipped with this step

      $ modprobe bluetooth 2>&1 | grep -i blacklisted

      good: Output matches what the step describes — the change is in effect on this host.

      not good: Empty or contradicting output means the change is not active yet. Apply the artifact, then run this again.

    2. 2module bluetooth is not loaded

      $ lsmod | grep -w bluetooth || echo "not loaded"

      good: You see "not loaded" — bluetooth is out of the kernel.

      not good: Output means bluetooth is still loaded: run "sudo modprobe -r bluetooth" (or reboot if it is in use).

    3. 3bluetooth can no longer autoload

      $ modprobe -n -v bluetooth

      good: "install /bin/false" (or an error) — nothing can pull it in automatically.

      not good: An "insmod …bluetooth.ko" line means the blacklist did not take: check /etc/modprobe.d/ and run "sudo depmod -a".

    4. 4module cramfs is not loaded

      $ lsmod | grep -w cramfs || echo "not loaded"

      good: You see "not loaded" — cramfs is out of the kernel.

      not good: Output means cramfs is still loaded: run "sudo modprobe -r cramfs" (or reboot if it is in use).

    5. 5cramfs can no longer autoload

      $ modprobe -n -v cramfs

      good: "install /bin/false" (or an error) — nothing can pull it in automatically.

      not good: An "insmod …cramfs.ko" line means the blacklist did not take: check /etc/modprobe.d/ and run "sudo depmod -a".

    6. 6module dccp is not loaded

      $ lsmod | grep -w dccp || echo "not loaded"

      good: You see "not loaded" — dccp is out of the kernel.

      not good: Output means dccp is still loaded: run "sudo modprobe -r dccp" (or reboot if it is in use).

    7. 7dccp can no longer autoload

      $ modprobe -n -v dccp

      good: "install /bin/false" (or an error) — nothing can pull it in automatically.

      not good: An "insmod …dccp.ko" line means the blacklist did not take: check /etc/modprobe.d/ and run "sudo depmod -a".

    8. 8module freevxfs is not loaded

      $ lsmod | grep -w freevxfs || echo "not loaded"

      good: You see "not loaded" — freevxfs is out of the kernel.

      not good: Output means freevxfs is still loaded: run "sudo modprobe -r freevxfs" (or reboot if it is in use).

    9. 9freevxfs can no longer autoload

      $ modprobe -n -v freevxfs

      good: "install /bin/false" (or an error) — nothing can pull it in automatically.

      not good: An "insmod …freevxfs.ko" line means the blacklist did not take: check /etc/modprobe.d/ and run "sudo depmod -a".

    10. 10module hfsplus is not loaded

      $ lsmod | grep -w hfsplus || echo "not loaded"

      good: You see "not loaded" — hfsplus is out of the kernel.

      not good: Output means hfsplus is still loaded: run "sudo modprobe -r hfsplus" (or reboot if it is in use).

    11. 11hfsplus can no longer autoload

      $ modprobe -n -v hfsplus

      good: "install /bin/false" (or an error) — nothing can pull it in automatically.

      not good: An "insmod …hfsplus.ko" line means the blacklist did not take: check /etc/modprobe.d/ and run "sudo depmod -a".

    12. 12module jffs2 is not loaded

      $ lsmod | grep -w jffs2 || echo "not loaded"

      good: You see "not loaded" — jffs2 is out of the kernel.

      not good: Output means jffs2 is still loaded: run "sudo modprobe -r jffs2" (or reboot if it is in use).

    13. 13jffs2 can no longer autoload

      $ modprobe -n -v jffs2

      good: "install /bin/false" (or an error) — nothing can pull it in automatically.

      not good: An "insmod …jffs2.ko" line means the blacklist did not take: check /etc/modprobe.d/ and run "sudo depmod -a".

    14. 14module n_hdlc is not loaded

      $ lsmod | grep -w n_hdlc || echo "not loaded"

      good: You see "not loaded" — n_hdlc is out of the kernel.

      not good: Output means n_hdlc is still loaded: run "sudo modprobe -r n_hdlc" (or reboot if it is in use).

    15. 15n_hdlc can no longer autoload

      $ modprobe -n -v n_hdlc

      good: "install /bin/false" (or an error) — nothing can pull it in automatically.

      not good: An "insmod …n_hdlc.ko" line means the blacklist did not take: check /etc/modprobe.d/ and run "sudo depmod -a".

    16. 16module rds is not loaded

      $ lsmod | grep -w rds || echo "not loaded"

      good: You see "not loaded" — rds is out of the kernel.

      not good: Output means rds is still loaded: run "sudo modprobe -r rds" (or reboot if it is in use).

    17. 17rds can no longer autoload

      $ modprobe -n -v rds

      good: "install /bin/false" (or an error) — nothing can pull it in automatically.

      not good: An "insmod …rds.ko" line means the blacklist did not take: check /etc/modprobe.d/ and run "sudo depmod -a".

    18. 18module tipc is not loaded

      $ lsmod | grep -w tipc || echo "not loaded"

      good: You see "not loaded" — tipc is out of the kernel.

      not good: Output means tipc is still loaded: run "sudo modprobe -r tipc" (or reboot if it is in use).

    19. 19tipc can no longer autoload

      $ modprobe -n -v tipc

      good: "install /bin/false" (or an error) — nothing can pull it in automatically.

      not good: An "insmod …tipc.ko" line means the blacklist did not take: check /etc/modprobe.d/ and run "sudo depmod -a".

    20. 20module udf is not loaded

      $ lsmod | grep -w udf || echo "not loaded"

      good: You see "not loaded" — udf is out of the kernel.

      not good: Output means udf is still loaded: run "sudo modprobe -r udf" (or reboot if it is in use).

    21. 21udf can no longer autoload

      $ modprobe -n -v udf

      good: "install /bin/false" (or an error) — nothing can pull it in automatically.

      not good: An "insmod …udf.ko" line means the blacklist did not take: check /etc/modprobe.d/ and run "sudo depmod -a".

    22. 22nothing important broke

      $ systemctl --failed --no-legend; journalctl -p err -b --since "10 min ago" | tail -20

      good: No failed units and no new kernel/service errors — the change was safe on this host.

      not good: A failed unit or a new error right after the change is your signal to revert with: sudo sed -i '/^blacklist bluetooth$/d; /^blacklist cramfs$/d; /^blacklist dccp$/d; /^blacklist freevxfs$/d; /^blacklist hfsplus$/d; /^blacklist jffs2$/d; /^blacklist n_hdlc$/d; /^blacklist rds$/d; /^blacklist tipc$/d; /^blacklist udf$/d' /etc/modprobe.d/blacklist.conf

    generated artifact

    /etc/modprobe.d/ksl-blacklist.conf
    # generated by kernel-surface-ledger - revert: kernel-surface-ledger generate blacklist_module
    blacklist bluetooth
    install bluetooth /bin/false
    blacklist cramfs
    install cramfs /bin/false
    blacklist dccp
    install dccp /bin/false
    blacklist freevxfs
    install freevxfs /bin/false
    blacklist hfsplus
    install hfsplus /bin/false
    blacklist jffs2
    install jffs2 /bin/false
    blacklist n_hdlc
    install n_hdlc /bin/false
    blacklist rds
    install rds /bin/false
    blacklist tipc
    install tipc /bin/false
    blacklist udf
    install udf /bin/false
    

    generated for review — ksl never applies hardening itself

  2. step 2seccomp_filter

    perf_event_open
    breakage: none2 CVEs killed

    what could break

    perf tool (e.g., perf record) could fail due to blocked perf_event_open

    detect it worked

    detection
    dmesg | grep -i seccomp

    revert

    revert
    sed -i '/seccomp_filter=perf_event_open/d' /etc/default/grub && update-grub

    check this — did step 2 work?

    1. 1the check shipped with this step

      $ dmesg | grep -i seccomp

      good: Output matches what the step describes — the change is in effect on this host.

      not good: Empty or contradicting output means the change is not active yet. Apply the artifact, then run this again.

    2. 2perf_event_open is gated by kernel.perf_event_paranoid

      $ sysctl kernel.perf_event_paranoid

      good: The value shown is the restricted one, so an ordinary user can no longer use perf_event_open.

      not good: An unrestricted value means perf_event_open is still reachable by any local user. Re-apply the step's artifact.

    3. 3nothing important broke

      $ systemctl --failed --no-legend; journalctl -p err -b --since "10 min ago" | tail -20

      good: No failed units and no new kernel/service errors — the change was safe on this host.

      not good: A failed unit or a new error right after the change is your signal to revert with: sed -i '/seccomp_filter=perf_event_open/d' /etc/default/grub && update-grub

    generated artifact

    /etc/ksl/seccomp_filter.conf
    # generated by kernel-surface-ledger - revert: kernel-surface-ledger revert
    {
      "defaultAction": "SCMP_ACT_ERRNO",
      "syscalls": [
        {"name": "execve", "action": "SCMP_ACT_ALLOW"},
        {"name": "exit", "action": "SCMP_ACT_ALLOW"},
        {"name": "exit_group", "action": "SCMP_ACT_ALLOW"},
        {"name": "rt_sigreturn", "action": "SCMP_ACT_ALLOW"},
        {"name": "rt_sigaction", "action": "SCMP_ACT_ALLOW"},
        {"name": "futex", "action": "SCMP_ACT_ALLOW"},
        {"name": "restart_syscall", "action": "SCMP_ACT_ALLOW"},
        {"name": "mmap", "action": "SCMP_ACT_ALLOW"},
        {"name": "munmap", "action": "SCMP_ACT_ALLOW"},
        {"name": "mprotect", "action": "SCMP_ACT_ALLOW"},
        {"name": "brk", "action": "SCMP_ACT_ALLOW"},
        {"name": "read", "action": "SCMP_ACT_ALLOW"},
        {"name": "write", "action": "SCMP_ACT_ALLOW"},
        {"name": "close", "action": "SCMP_ACT_ALLOW"}
      ]
    }
    

    generated for review — ksl never applies hardening itself

  3. step 3sysctl_set

    kernel.dmesg_restrict=1kernel.kptr_restrict=2kernel.modules_disabled=1kernel.unprivileged_userns_clone=0
    breakage: low5 CVEs killed26 weight

    what could break

    A container runtime such as Docker that relies on unprivileged user namespaces may fail to start containers.

    detect it worked

    detection
    journalctl -u docker | grep 'permission denied'

    revert

    revert
    sysctl -w kernel.dmesg_restrict=0 kernel.kptr_restrict=0 kernel.modules_disabled=0 kernel.unprivileged_userns_clone=1

    check this — did step 3 work?

    1. 1the check shipped with this step

      $ journalctl -u docker | grep 'permission denied'

      good: Output matches what the step describes — the change is in effect on this host.

      not good: Empty or contradicting output means the change is not active yet. Apply the artifact, then run this again.

    2. 2sysctl kernel.dmesg_restrict is set

      $ sysctl kernel.dmesg_restrict

      good: The printed value is the restricted one from this step.

      not good: A different value means the step is not applied on this host.

    3. 3sysctl kernel.kptr_restrict is set

      $ sysctl kernel.kptr_restrict

      good: The printed value is the restricted one from this step.

      not good: A different value means the step is not applied on this host.

    4. 4sysctl kernel.modules_disabled is set

      $ sysctl kernel.modules_disabled

      good: The printed value is the restricted one from this step.

      not good: A different value means the step is not applied on this host.

    5. 5sysctl kernel.unprivileged_userns_clone is set

      $ sysctl kernel.unprivileged_userns_clone

      good: The printed value is the restricted one from this step.

      not good: A different value means the step is not applied on this host.

    6. 6nothing important broke

      $ systemctl --failed --no-legend; journalctl -p err -b --since "10 min ago" | tail -20

      good: No failed units and no new kernel/service errors — the change was safe on this host.

      not good: A failed unit or a new error right after the change is your signal to revert with: sysctl -w kernel.dmesg_restrict=0 kernel.kptr_restrict=0 kernel.modules_disabled=0 kernel.unprivileged_userns_clone=1

    generated artifact

    /etc/sysctl.d/99-ksl-hardening.conf
    # generated by kernel-surface-ledger - revert: sysctl -w kernel.dmesg_restrict=0 kernel.kptr_restrict=0 kernel.modules_disabled=0 kernel.unprivileged_userns_clone=1
    # CVE-2016-5195: kernel.dmesg_restrict=1
    # CVE-2016-5195: kernel.kptr_restrict=2
    # CVE-2016-5195: kernel.modules_disabled=1
    # CVE-2016-5195: kernel.unprivileged_userns_clone=0
    

    generated for review — ksl never applies hardening itself

  4. step 4seccomp_filter

    userfaultfd
    breakage: none1 CVEs killed

    what could break

    A checkpoint/restore tool such as CRIU that uses userfaultfd could be blocked by the seccomp filter.

    detect it worked

    detection
    ausearch -m seccomp -i | grep userfaultfd

    revert

    revert
    sudo rm -f /etc/seccomp.d/userfaultfd && sudo systemctl restart systemd-logind

    check this — did step 4 work?

    1. 1the check shipped with this step

      $ ausearch -m seccomp -i | grep userfaultfd

      good: Output matches what the step describes — the change is in effect on this host.

      not good: Empty or contradicting output means the change is not active yet. Apply the artifact, then run this again.

    2. 2userfaultfd is gated by vm.unprivileged_userfaultfd

      $ sysctl vm.unprivileged_userfaultfd

      good: The value shown is the restricted one, so an ordinary user can no longer use userfaultfd.

      not good: An unrestricted value means userfaultfd is still reachable by any local user. Re-apply the step's artifact.

    3. 3nothing important broke

      $ systemctl --failed --no-legend; journalctl -p err -b --since "10 min ago" | tail -20

      good: No failed units and no new kernel/service errors — the change was safe on this host.

      not good: A failed unit or a new error right after the change is your signal to revert with: sudo rm -f /etc/seccomp.d/userfaultfd && sudo systemctl restart systemd-logind

    generated artifact

    /etc/ksl/seccomp_filter.conf
    # generated by kernel-surface-ledger - revert: kernel-surface-ledger revert
    {
      "defaultAction": "SCMP_ACT_ERRNO",
      "syscalls": [
        {
          "names": [
            "execve",
            "exit",
            "exit_group",
            "rt_sigreturn",
            "rt_sigaction",
            "futex",
            "restart_syscall",
            "mmap",
            "munmap",
            "mprotect",
            "brk",
            "read",
            "write",
            "close"
          ],
          "action": "SCMP_ACT_ALLOW"
        }
      ]
    }
    

    generated for review — ksl never applies hardening itself

  5. step 5seccomp_filter

    io_uring_setup
    breakage: low3 CVEs killed

    what could break

    A workload using io_uring, such as fio, could fail to start io_uring contexts.

    detect it worked

    detection
    ausearch -m SECCOMP -i | grep io_uring_setup

    revert

    revert
    sed -i '/io_uring_setup/d' /etc/seccomp.d/default.profile && systemctl restart systemd-seccomp

    check this — did step 5 work?

    1. 1the check shipped with this step

      $ ausearch -m SECCOMP -i | grep io_uring_setup

      good: Output matches what the step describes — the change is in effect on this host.

      not good: Empty or contradicting output means the change is not active yet. Apply the artifact, then run this again.

    2. 2io_uring_setup is gated by kernel.io_uring_disabled

      $ sysctl kernel.io_uring_disabled

      good: The value shown is the restricted one, so an ordinary user can no longer use io_uring_setup.

      not good: An unrestricted value means io_uring_setup is still reachable by any local user. Re-apply the step's artifact.

    3. 3nothing important broke

      $ systemctl --failed --no-legend; journalctl -p err -b --since "10 min ago" | tail -20

      good: No failed units and no new kernel/service errors — the change was safe on this host.

      not good: A failed unit or a new error right after the change is your signal to revert with: sed -i '/io_uring_setup/d' /etc/seccomp.d/default.profile && systemctl restart systemd-seccomp

    generated artifact

    /etc/ksl/seccomp_filter.conf
    # generated by kernel-surface-ledger - revert: kernel-surface-ledger revert
    {
      "defaultAction": "SCMP_ACT_ERRNO",
      "syscalls": [
        {
          "names": [
            "execve",
            "exit",
            "exit_group",
            "rt_sigreturn",
            "rt_sigaction",
            "futex",
            "restart_syscall",
            "mmap",
            "munmap",
            "mprotect",
            "brk",
            "read",
            "write",
            "close"
          ],
          "action": "SCMP_ACT_ALLOW"
        }
      ]
    }
    

    generated for review — ksl never applies hardening itself

05 / blast radius

Impact graph

Before you apply a step, see what it touches: each hardening step, the exact kernel surface it removes, and the kernel capability plus the user-space workloads that depend on that surface. Click any node to isolate its paths.

hardening step → kernel surface removed → kernel capability and user-space functions that depend on it
HARDENING STEPSURFACE REMOVEDWHAT DEPENDS ON ITstep 1 · blacklist_module — 5 CVEs · risk nonestep 1 · blacklist_module5 CVEs · risk nonemod.bluetooth — module · bluetooth · weight 6mod.bluetoothmodule · bluetooth · weight 6kernel: bluetooth — kernel capabilitykernel: bluetoothkernel capabilityno observed user — orphaned — nothing brokeno observed userorphaned — nothing brokemod.legacy_fs — module · fs · weight 5mod.legacy_fsmodule · fs · weight 5kernel: fs — kernel capabilitykernel: fskernel capabilitymod.dccp — module · net · weight 7mod.dccpmodule · net · weight 7kernel: net — kernel capabilitykernel: netkernel capabilitymod.n_hdlc — module · tty · weight 5.5mod.n_hdlcmodule · tty · weight 5.5kernel: tty — kernel capabilitykernel: ttykernel capabilitymod.rds — module · net · weight 6.5mod.rdsmodule · net · weight 6.5mod.tipc — module · net · weight 6.5mod.tipcmodule · net · weight 6.5step 2 · seccomp_filter — 2 CVEs · risk nonestep 2 · seccomp_filter2 CVEs · risk nonesc.perf_event_open — syscall · perf · weight 7.5sc.perf_event_opensyscall · perf · weight 7.5kernel: perf — kernel capabilitykernel: perfkernel capabilitystep 3 · sysctl_set — 5 CVEs · risk lowstep 3 · sysctl_set5 CVEs · risk lowcfg.dmesg_open — sysctl · infoleak · weight 4cfg.dmesg_opensysctl · infoleak · weight 4kernel: infoleak — kernel capabilitykernel: infoleakkernel capabilitycfg.no_kptr_restrict — sysctl · infoleak · weight 5cfg.no_kptr_restrictsysctl · infoleak · weight 5cfg.module_autoload — sysctl · modules · weight 7.5cfg.module_autoloadsysctl · modules · weight 7.5kernel: modules — kernel capabilitykernel: moduleskernel capabilityns.userns_unpriv — namespace · namespaces · weight 9.5ns.userns_unprivnamespace · namespaces · weight 9.5kernel: namespaces — kernel capabilitykernel: namespaceskernel capabilitydockerd (docker.service) — user-space workloaddockerd (docker.service)user-space workloadstep 4 · seccomp_filter — 1 CVEs · risk nonestep 4 · seccomp_filter1 CVEs · risk nonesc.userfaultfd — syscall · mm · weight 8sc.userfaultfdsyscall · mm · weight 8kernel: mm — kernel capabilitykernel: mmkernel capabilitystep 5 · seccomp_filter — 3 CVEs · risk lowstep 5 · seccomp_filter3 CVEs · risk lowsc.io_uring_setup — syscall · io_uring · weight 9sc.io_uring_setupsyscall · io_uring · weight 9kernel: io_uring — kernel capabilitykernel: io_uringkernel capabilitynginx (nginx.service) — user-space workloadnginx (nginx.service)user-space workload

Edges come straight from the report: a step's targets, each target's subsystem, and the workloads whose touches include it. A target reaching only “no observed user” is orphaned surface — removing it broke nothing during the observation window.

06 / provenance

Where the AI is — and is not

The scoring engine is fully deterministic. The model explains and generates; it never decides.

what the model does

  • Causal narration of each blame edge — why a workload needs this surface, what primitive an attacker gains, what the alternative is.(5 of 5 ledger rows narrated here)
  • Artifact synthesis — applicable modprobe.d blacklists, per-service seccomp-BPF filters, systemd drop-ins, sysctl fragments.
  • Breakage prediction — what could break, how to detect it, how to revert it.

what the model does not do

It never decides. Every weight, gate, debt figure, orphan set and plan ordering on this page comes from the deterministic engine. Disabling the model entirely produces byte-identical scored output — this is enforced by a test in the repository.

verify determinism
python ksl.py scan --raw fixtures/raw-demo.json --no-explain
python ksl.py check report.json

Collector is strictly read-only: it never loads or unloads a module, never writes outside its output path, and degrades to a partial report as a non-root user. Report produced by ksl 0.1.0.

Kernel Surface Ledger (ksl) — kernel attack surface as an accountability problem. Reports are rendered from the frozen report.schema.json contract; drag any schema-valid report.json onto this page.