Repository navigation
The security report
GNOME Settings has a shield in Privacy & Security. Clicking it opens a dialog
that says "Protected" or "Security Checks Failed" and offers to copy a
technical report. Everything it knows comes from fwupd's
GetHostSecurityAttrs, and fwupd's Host Security ID is an index of firmware
protections: Secure Boot, the SPI descriptor, Intel BootGuard, TPM
reconstruction.
Those matter, but a desktop user is asking something closer to "is this machine set up the way a careful person would set it up". Is the disk encrypted? Is the kernel locked down, are modules signed, is the IOMMU on, are the usual hardening sysctls set? None of that appears in the dialog, because fwupd reports on the OS only where it has a plugin for it. lynis answers those questions for servers, as a shell script that prints a long text report.
This OS answers both sets of questions in one list.
losos-security, in src/losos-security/, runs the OS-level checks and
serves them on the system bus as io.losos.Security1. It answers
GetHostSecurityAttrs, the same method name fwupd uses, with the same a{sv}
dictionary keys. Because the answers have fwupd's shape, the
gnome-control-center patch only asks a second bus name and files the answers
separately. It needs no second parser and no second widget. src/attr.rs pins
the key set against the code that reads it, gnome-control-center's
panels/privacy/firmware-security/cc-firmware-security-utils.c.
The attributes go into their own table, not into the HSI tables. fwupd defines the HSI levels for firmware, and filing "disk encryption" under HSI-1 would claim the two are equivalent when they are not.
Each check reports a FwupdSecurityAttrResult and a level. Unlike fwupd's,
it also reports the path it read and what it found there.
| Check | Reads |
|---|---|
| UEFI Secure Boot |
/sys/firmware/efi/efivars/SecureBoot-8be4df61-…, fifth byte |
| TPM 2.0 present | /sys/class/tpm/tpm0/tpm_version_major |
| Measured boot | /sys/kernel/security/tpm0/binary_bios_measurements |
| Disk encryption |
/sys/block/*/dm/uuid, prefix CRYPT-LUKS
|
| Verified system image |
/sys/block/*/dm/uuid, prefix CRYPT-VERITY
|
| Kernel lockdown |
/sys/kernel/security/lockdown, the bracketed mode |
| Module signature enforcement | /sys/module/module/parameters/sig_enforce |
| IOMMU | /sys/class/iommu |
| Kernel address exposure |
kernel.kptr_restrict ≥ 1 |
| Kernel log access |
kernel.dmesg_restrict ≥ 1 |
| Unprivileged BPF |
kernel.unprivileged_bpf_disabled ≥ 1 |
| BPF JIT hardening |
net.core.bpf_jit_harden ≥ 1 |
Two rules matter here, and a careless change can break either.
Every check names where it looked. If a verdict comes without its
evidence, nobody can tell when it is wrong. The evidence goes in the
Description field, so the panel shows it when the row is expanded.
Every check is rooted. No check opens an absolute path. They all go
through Context::path, which prefixes a configurable root. That one
function call makes the suite testable: tests/checks.rs builds a fixture
directory of sysfs files and tests every check passing and failing, with no
TPM and no root.
The overall level is the weakest link, the highest level at which every check
passed. It is not a score or a percentage. A machine with nine passes and one
level-1 failure has a level-0 problem, and an average would hide it. A level
with no checks in it does not count as passed. all() over an empty iterator
is true, so without that rule an untested level would report the best possible
answer.
nixos/pkgs/patches/gnome-control-center/0002-firmware-security-report-os-level-checks.patch
does three things:
- Adds a third D-Bus proxy, to
io.losos.Security1, beside the two fwupd ones, and files its reply into a separate table through the existing parser. - Counts replies to decide whether the page is available, instead of leaving it to one callback. The two providers can reply in either order, so neither can decide alone that there is nothing to show. The "unavailable" page appears only when both have failed. The fwupd failure path now counts itself, which upstream never needed. Without that, a machine with the OS provider and no fwupd would wait forever for a verdict. Upstream hides the page on a virtual machine, where a firmware index means nothing. If any provider answered, the page shows anyway, because the OS checks still apply there.
- Lists the checks in the dialog. Upstream shows them only inside the copied technical report. That made sense while every check was about firmware the reader cannot change from here. This list includes a lockdown mode and four sysctls, and a reader who is told which one failed can fix it.
losos-security # human-readable; exit status is the verdict
losos-security --json
losos-security --root ./fixture # every check against a fixture treeThe service is bus-activated, not enabled. The unit has no [Install]
section. io.losos.Security1.service in dbus-1/system-services names
SystemdService=, so dbus-daemon hands the start to systemd and the sandbox
in losos-security.service applies. It runs as root, because two of the paths
above are not world-readable. The sandbox then takes away everything else a
root process could do. It has no capabilities, no writable filesystem and no
network namespace, may open only AF_UNIX sockets, and may make only the
@system-service system calls. A security checker that an attacker could
exploit would make the machine less safe.
Generated from docs/ in the repository at every change; edit the pages there, since an edit made here is overwritten.
- LosOS Desktop
- Building
- When something goes wrong
- Reporting a problem
-
The system
- Everything systemd, and the exceptions
- Virtual machine desktop
- Peripherals in machines of their own
- The network machine
- The files machine
- The portal machine
- Where the OS lives
- Hibernation
- Hardware and NVIDIA
- Boot loader and boot screen
- Secure Boot
- The installer
- The Windows installer
- Trying it in quickemu
- First-boot setup
- Signing in
- Security keys and smart cards
- More than one person
- Company accounts
- Releases and GHCR
- The memory allocator
- The security report
- Kernel hardening
- Schizo mode
- VPN
-
Desktop and apps
- GTK and Qt on a phone
- One icon theme
- Danube
- System-wide ad blocking
- The terminal
- Ask derisk
- The Store
- The Agent
- Active users and the choice screens
- LosOS boxes
- Windows app support
- The gaming machine
- Focus mode
- Android app support
- macOS app support
- arm64 macOS machines
- App windows
- Backups to a LosOS box
- Screenshots
- Building blocks
- Phones
- History and gaps