Multi-Layer Automated Hardening of System Services
Category: Vulnerability research
Location: any
Contact:
Lucas Crijns
Background
systemd is the default service manager on most major Linux distributions. In systemd so-called ‘unit’ files define services that are loaded upon startup, when a certain event occurs or on a timer. Most system services have a large attack surface through the syscalls they can issue, the files they can read or write, the capabilities they have been assigned or the network endpoints it can reach. systemd ships with a rich set of sandboxing and security directives to limit the access a service has. Examples of such directives are:
ProtectSystem=SystemCallFilter=CapabilityBoundingSet=RestrictAddressFamilies=PrivateTmp=NoNewPrivileges=To measure how many of these directives are used by a particular unit file,systemdcomes bundled withsystemd-analyze securitywhich gives a score from 0.0 (completely isolated) to 10.0 (exposed).
In practice, many unit-files shipped by major distributions have scores of 8–10. Such a high score can be due to the broad access a service needs, but often it is clear that the distribution did not attempt any hardening. One example would be the unit-file for the SSH Daemon on Ubuntu 24.04 LTS which has a score of 9.6:
[Unit]
Description=OpenBSD Secure Shell server
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run
[Service]
EnvironmentFile=-/etc/default/ssh
ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/usr/sbin/sshd -t
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
Type=notify
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
Alias=sshd.service
This service unit-file does not include any of the hardening directives systemd comes bundled with. To improve this, the operator must:
- discover, by reading documentation and source code, what the service actually needs,
- translate that into the correct combination of systemd directives, optionally a MAC policy (SELinux/AppArmor),
- validate that the resulting configuration does not break the service under realistic workloads, and
- re-validate after every package upgrade, because new code paths may need new syscalls, paths, or capabilities.
No existing tool performs this entire loop. The closest, shh (“Systemd Hardening Helper”), wraps a service with strace, observes its behaviour, and emits a drop-in hardening config. It is explicitly non-portable across kernels, libc versions, and systemd releases, and it only produces systemd directives. Hence, it does not generate complementary SELinux or AppArmor policy. Upstream systemd has an open feature request for an aa-genprof-equivalent mode for systemd-analyze security (systemd/systemd#26994). However, it remains unimplemented.
The gap this project addresses is the absence of a cross-layer hardening pipeline that combines static and dynamic analysis, generates a coherent confinement stack across systemd, MAC (SELinux/AppArmor), validates the result with LLM-synthesised functional tests, and is portable across distributions.
Objectives
The aim of the work is to design, implement, and evaluate a tool that automatically hardens systemd services while guaranteeing functionality.
Specifically:
- Multi-source profiling. Combine static analysis of the unit file and package contents with dynamic tracing (
strace,auditd, etc.) to capture syscalls, file accesses, capabilities, network endpoints, and IPC usage. - Cross-layer hardening generation. From profiling passes, produce a coherent confinement stack:
- a
systemd drop-in (ProtectSystem=,ReadWritePaths=,SystemCallFilter=,CapabilityBoundingSet=,RestrictAddressFamilies=, etc.), - optionally, a complementary SELinux CIL module or AppArmor profile that confines the service domain to the observed labels/paths/ports, and
- extra rules for confinement technologies like Landlock, bwrap or similar.
- a
- LLM-validated functional testing. Use a local LLM to synthesise
runNixOSTest-style or similar standalone tests from the service’s declared behaviour (unit file, man page, package metadata). Run each candidate hardening config in an isolated VM, execute the functional tests, and select the most restrictive config that passes. The LLM is also used to diagnose failures and propose minimal relaxations.
Requirements
- Strong understanding of
systemd, Linux namespaces, capabilities, cgroups, MAC (SELinux/AppArmor), etc. - Proficiency in at least one of Python, Rust, or Go for tooling.
- Experience with VMs or containers (QEMU/KVM, LXC, Docker/Podman) for isolated testing.
- Familiarity with NixOS is a plus, given the
runNixOSTest framework andnix flake checkintegration. - Familiarity with LLMs and prompt engineering is a plus, given the LLM-based test synthesis and failure diagnosis.
- Mindset to learn the additional skills.
References and sources
Existing tools
shh - Systemd Hardening Helper (Synacktiv): Rust-based tool that wraps a service withstrace, profiles syscalls/filesystem/network/capabilities, and emits a drop-in hardening config. Explicitly non-portable; no functional validation.
systemd-analyze security : Built-in scorer that rates a service unit’s exposure from 0.0 to 10.0 based on sandboxing directives. Measures only; does not generate, apply, or validate.
udica - SELinux policy generator for containers: Inspects container JSON spec, reads capabilities/ports/mounts, composes a CIL SELinux module from predefined templates. Container-only; no runtime observation.
audit2allow / sepolicy generate / sepolgen : Reactive SELinux policy helpers. Convert AVC denials intoallowrules or local modules. Fundamentally reactive; need denials and permissive mode.AppArmor
aa-genprof / aa-logprof : Behavioural profile learning for AppArmor. AppArmor-specific; path-centric; interactive.Landlock ecosystem: Kernel LSM letting a process restrict its own filesystem and TCP access. No mature tool infers Landlock rules from observing a
systemdservice and injects them into the unit.Wrappers :
- Landrun : https://github.com/Zouuup/landrun
- Island : https://github.com/landlock-lsm/island
nixos-harden-systemd : NixOS-specific framework that hooks into NixOS module tests. Enumerates boolean hardening options, applies combinations, re-runs the package’s own NixOS tests. NixOS-only; boolean-only.
systemd issue #26994: Open feature request for anaa-genprof-equivalent mode forsystemd-analyze security. Remains unimplemented.
Relevant research
Ciri - LLM-based misconfiguration detection (ICSE 2025): Uses LLMs with few-shot learning to detect misconfigurations in config files/diffs across many systems.
“Quantifiable Run-time Kernel Attack Surface Reduction” (kRazor, DIMVA 2014): Demonstrated per-application kernel attack-surface reduction by tracing kernel functions, with reductions of 30–80%. Relevant conceptually to syscall filtering.