Before you start#
Review ELF and ABI, kernel modules, LSM policy, and cryptographic trust. This lesson reads upstream Linux v6.12 as a historical baseline, not a current security recommendation. The examples are source reasoning; firmware, bootloader, distribution patches, kernel configuration, keys and policy determine a real system's behavior.
Learning goals#
Separate firmware boot verification, kernel module verification, lockdown, IMA measurement and appraisal, and EVM metadata protection. Follow concrete module and appraisal failure branches without assuming that a signed component is correct or that an unobserved boot was verified.
Source walkthrough#
- Firmware and loader
- Platform image verification and boot-chain policy
- Module signatures and lockdown
- Kernel verifier and reason-specific restrictions
- IMA
- Policy-selected measurement and appraisal
- EVM and verity
- Protect distinct metadata or content under configured trust
UEFI Secure Boot is a firmware-controlled boot policy for executable images in a platform trust environment. Firmware maintains key and revocation databases and checks images according to its configuration. A deployment may use a first-stage loader such as shim, a bootloader, and a kernel image, but which component verifies which next component depends on the actual boot chain and configuration. Shim and its machine-owner-key mechanism are separate userspace/boot projects, not identical to the upstream kernel's module-signature verifier. A trusted key can authenticate a signed image under the verifier's policy; it does not prove that image is safe, current, correctly configured, or free of vulnerabilities.
In the EFI-stub path, efi_get_secureboot asks the EFI secure-boot mode helper and returns an unknown status if it cannot determine the mode. When firmware reports the mode enabled, the code also examines a shim state variable under the documented conditions. This is evidence of a particular status-handling path, not proof that a particular host booted through this stub or that this function verifies every PE image itself. PE/COFF image verification can occur in firmware, shim or other selected boot components; inspect that component and its actual policy rather than attributing an entire chain to one kernel function. Kernel and distribution support for automatically enabling lockdown under Secure Boot can vary; firmware reporting Secure Boot enabled does not universally prove an identical lockdown mode on every distribution.
A separate kernel PE verification helper, verify_pefile_signature, parses a PE image, locates its signature wrapper, verifies the PKCS#7 signature against the caller-supplied trust and usage, then calculates and compares the PE digest. Parsing, missing signature, unavailable crypto or key, and a rejected signature have distinct errors. The helper frees its temporary digest on its error/exit path. Its existence does not show that firmware or shim called this kernel function before the kernel started: identify the actual kernel caller and boot path before attributing a live verification to it.
In certs/system_keyring.c, secondary, machine and platform trusted keyring pointers are conditional on their respective configuration symbols; PKCS#7 trust selection can fall back to built-in keys or return -ENOKEY for an unavailable platform keyring according to the requested selector. The UEFI certificate loader reads configured firmware variables when runtime services and platform quirks permit, and its MokIgnoreDB handling can skip the firmware db source. Missing variables or unsupported firmware services are not proof that an image was verified by a different component. These are source-level options, not a claim about the current machine's enrolled keys.
Kernel keyrings and signed modules#
The kernel can maintain several keyrings with different sources and trust roles. Depending on configuration and platform, built-in trusted keys can be compiled into the kernel; secondary trusted keys can be added under controlled trust rules; platform or machine keyrings can expose selected firmware or owner keys. Their existence, linking and use differ by configuration and distribution. A key present in one store does not automatically imply that every verifier consults it, and revocation or blacklist policy can reject a signature even if a certificate looks familiar. Trace the verifier and configured keyrings for the operation in question instead of treating “trusted key” as a universal set.
A module signature is appended to the module in a format recognized by the kernel. The signing and verification path uses PKCS#7 signature infrastructure and configured trust keys. Verification authenticates the bytes under an accepted key and algorithm; it does not prove that module code is race-free, compatible with the running kernel, or safe to load. Module version and vermagic checks are separate compatibility mechanisms. Signature enforcement can be selected by configuration or runtime policy, and a non-enforcing system may permit some unverified modules while marking the kernel tainted. Taint records a state useful for diagnostics; it does not repair an unsafe module.
In module_sig_check, the following exact v6.12 GPL-2.0-or-later excerpt, copyright Red Hat and contributors, follows verification and error classification; surrounding lines are omitted:
if (is_module_sig_enforced()) {
pr_notice("Loading of %s is rejected\n", reason);
return -EKEYREJECTED;
}
return security_locked_down(LOCKDOWN_MODULE_SIGNATURE);
For an unsigned module, unsupported crypto or unavailable key, the preceding switch selects a reason. If signature enforcement is active, the branch rejects it with -EKEYREJECTED. Otherwise the function asks the lockdown LSM whether this signature-related operation is permitted. The earlier switch returns other errors immediately: malformed signatures, bad signature checks and allocation errors are not simply accepted as unsigned in permissive mode. A valid signature sets info->sig_ok and returns success from this checker, but the module loader has additional checks and can still fail.
A source-level case illustrates the difference. Module A has no signature marker and reaches the unsigned case. With signature enforcement on, the quoted branch rejects it. With enforcement off, the lockdown hook can still reject it. Module B has a malformed signature that causes a fatal verification error; that error is returned before the quoted permissive/lockdown path. Module C verifies successfully, but can still fail later compatibility or initialization checks. These are conditional outcomes of source branches, not a claim that any module was loaded in this lesson.
- Malformed or bad signature
Fatal verification errors return before the permissive path
- Unsigned or key unavailable
A reason string is chosen for the rejection notice
- Enforcement on
The loader rejects the module with -EKEYREJECTED
- Enforcement off
The lockdown hook decides whether LOCKDOWN_MODULE_SIGNATURE applies
- Valid signature
sig_ok is set; later loader checks can still fail
Lockdown is a reasoned restriction#
Lockdown is an LSM that restricts selected kernel operations according to a lockdown level and a lockdown_reason. It is not a universal synonym for Secure Boot, and its protection scope depends on registered hook call sites. In lockdown.c, lockdown_is_locked_down rejects an invalid reason and, when the current lockdown level covers the requested reason, returns -EPERM; otherwise it returns zero. The function may issue a rate-limited notice for a named reason. A zero from this specific hook is not authorization from all other policy, capability and module checks.
The check is lockdown_is_locked_down in security/lockdown/lockdown.c, v6.12, SPDX GPL-2.0 (exact, unabridged):
static int lockdown_is_locked_down(enum lockdown_reason what)
{
if (WARN(what >= LOCKDOWN_CONFIDENTIALITY_MAX,
"Invalid lockdown reason"))
return -EPERM;
if (kernel_locked_down >= what) {
if (lockdown_reasons[what])
pr_notice_ratelimited("Lockdown: %s: %s is restricted; see man kernel_lockdown.7\n",
current->comm, lockdown_reasons[what]);
return -EPERM;
}
return 0;
}
The function returns -EPERM only when the current level is at or above the requested reason, and it returns zero otherwise. The notice is rate-limited. The excerpt does not show how the level is chosen at boot or which other checks the caller performs.
The distinction between integrity and confidentiality levels concerns which classes of kernel interfaces are restricted. A configured forced level, a boot-time selection and a distribution's integration with EFI policy can lead to different states. Read the actual lockdown hook, reason enumeration and call site before asserting why an operation failed. The presence of /sys/kernel/security/lockdown or an EFI variable alone does not reveal the whole boot chain, trusted key inventory or policy configuration.
IMA measurement and appraisal#
The Integrity Measurement Architecture (IMA) can measure selected objects according to policy, recording digests and other template data in an event log and, where configured, extending a TPM Platform Configuration Register (PCR). Measurement records evidence; it does not by itself deny execution. Appraisal verifies selected file content against configured integrity metadata or signatures and can deny an operation under an enforcing policy. A system can measure without appraising, appraise different events from those it measures, or run without IMA entirely. The IMA file hooks select actions based on policy and the operation.
- IMA measurement
- Records digests in the event log and may extend a TPM PCR; does not deny by itself
- IMA appraisal
- Checks integrity xattr or module-signature data; can deny under enforcing policy
- EVM
- Protects selected security metadata with HMAC or a signature, not every byte of every file
- fs-verity and dm-verity
- Authenticate read-only file contents or device blocks against a trusted root
IMA uses an integrity information cache associated with an inode to track measurement and appraisal state, flags and digest-related information. Cache validity and invalidation depend on file state, policy and the relevant code path; a cached result is not a timeless assertion about every subsequent byte. The file and inode must remain referenced while a hook examines them, and IMA synchronizes per-inode integrity work using its own locking. Concurrent modifications, writes and policy changes are part of the actual implementation contract; do not infer that a filename alone identifies immutable content.
In ima_appraise_measurement, the following v6.12 GPL-2.0-only excerpt is from the missing-metadata branch, copyright IBM and contributors; surrounding conditions and later handling are omitted:
status = INTEGRITY_NOLABEL;
if (file->f_mode & FMODE_CREATED)
iint->flags |= IMA_NEW_FILE;
The first statement records a missing integrity label. The next condition identifies a newly created file and sets an IMA flag. In the immediately following source, a new file can be treated as passing under specified signature/size conditions; otherwise the missing-label status remains. Earlier code also distinguishes an xattr read error from a missing xattr, and a permitted appended module signature can alter the route. Later code evaluates EVM status, verifies xattr or module-signature data, stores status and reports the outcome. A failed appraisal status becomes an access denial only in the applicable enforcing policy and hook context; do not claim that every missing xattr always fails every open.
For a concrete synthetic case, assume an existing file is subject to an enforcing appraisal rule requiring a valid IMA signature, has no qualifying signature metadata, and has no permitted module-signature fallback. The missing-label branch does not acquire the new-file exception merely because the application wants to read it. Under that specified policy the appraisal can deny access. If the policy instead measures the file without appraising it, a measurement record is not itself a denial. The exact error, audit output and file operation depend on the actual hook and policy. No live policy was changed to create this example.
EVM, verity and attestation#
EVM protects selected security metadata, including integrity-related extended attributes and associated metadata under its configured HMAC or signature scheme. It does not simply hash and authenticate every byte of every file by itself. The scope of protected xattrs, keys, signatures, filesystem support and policy matters. IMA appraisal may consult EVM verification for metadata before verifying IMA content metadata; a missing or invalid EVM value can affect that appraisal path. See evm_main.c and the exact IMA branch rather than treating IMA and EVM as interchangeable.
fs-verity authenticates individual read-only file contents using a Merkle-tree mechanism when properly enabled and trusted by a consumer; dm-verity verifies blocks of a configured device against a trusted root hash. Encryption addresses confidentiality and is not automatically either content authentication or a trusted root-hash distribution mechanism. These mechanisms can complement signatures, IMA and EVM, but their protected object, trust anchor and failure semantics differ. A writable filesystem with an encrypted block device is not automatically an appraised set of executable files.
A TPM PCR is an accumulated digest of measured events, not a list of readable file contents. A remote verifier can request a TPM quote covering selected PCRs and a fresh nonce, verify the quote with an appropriate attestation-key trust chain, replay the measurement log and compare the result and event values with its own policy. The fresh nonce helps prevent replay of an old quote. Even a valid quote and consistent log only establish what the measured chain and verifier policy cover; they do not prove absence of unmeasured runtime compromise, correct configuration of every device, or future integrity. Protecting the log, key enrollment, policy freshness and verifier decision are separate engineering tasks.
A trust-chain failure investigation#
Imagine a machine reports that firmware Secure Boot is enabled but refuses to load a module. First establish which kernel actually booted and whether the firmware-to-loader chain and kernel lockdown status were observed. Then distinguish a missing module signature, an unavailable signer key, an unsupported verification algorithm and an invalid signature. The source's error classification treats those differently. If enforcement is off but lockdown rejects LOCKDOWN_MODULE_SIGNATURE, the refusal follows a different branch from -EKEYREJECTED under enforced signatures. A valid signature still does not establish that the module's initialization succeeded. This is a reasoning plan, not an instruction to install or load a module.
IMA adds another possible decision. The integrity cache relates a particular inode's content and metadata state to a prior result; the applicable policy chooses whether a given event is measured, appraised or ignored. A file that is measured at execution time may not have been measured at every earlier modification, and a path in a log is not a stable identifier for all versions of the bytes. A verifier should compare the event's digest and relevant template data with an expected policy and understand which events were eligible for measurement. If an appraisal hook encounters an xattr read error other than missing data, the code follows a different error path from the synthetic missing-label case. This distinction prevents treating a storage or filesystem error as a simple policy mismatch.
A chain is only as informative as the verifiers and inputs actually observed. Firmware status, a bootloader's policy, the kernel's trusted-key configuration, module enforcement and an IMA policy are separate pieces of evidence. A distribution can supply custom trust integration or patches. Before concluding that a particular signature should be accepted, establish the exact kernel build, signature format, key source, revocation state and policy; avoid enrolling new keys or weakening checks while diagnosing a shared system.
Practice#
Read-only Linux observation
On your own authorized host or disposable guest, query existing state without enrollment, module loading, policy writes or firmware changes:
uname -r
if command -v mokutil >/dev/null 2>&1; then mokutil --sb-state; else echo 'mokutil unavailable'; fi
if [ -r /sys/kernel/security/lockdown ]; then cat /sys/kernel/security/lockdown; else echo 'lockdown status unavailable'; fi
if [ -d /sys/firmware/efi/efivars ]; then ls -ld /sys/firmware/efi/efivars; else echo 'EFI variables unavailable'; fi
if [ -r /sys/kernel/security/ima/ascii_runtime_measurements ]; then head -n 3 /sys/kernel/security/ima/ascii_runtime_measurements; else echo 'IMA log unavailable or restricted'; fi
mokutil reports the state it can query, not a complete boot-chain proof. The lockdown attribute, if present, shows kernel-reported selection rather than all LSM policy. The IMA log can expose paths and measurements; inspect it only when authorized and do not publish sensitive entries. Missing EFI, securityfs, tools, TPM, measurements or permission is a legitimate result, particularly in a guest. Record kernel and utility versions and do not use sudo to force access.
Source-only alternative: construct a table for unsigned module A with enforcement on, unsigned A with enforcement off and lockdown denial, and malformed module B. The source gives -EKEYREJECTED, a lockdown result, and an earlier fatal verifier result respectively. Add the existing-file missing-IMA-signature assumptions and distinguish its appraisal result from a measurement-only policy. Deliver this table or the actual read-only observations, explicitly marking what was not checked.
Knowledge check#
- Why does Secure Boot status alone not prove a module signature was accepted?
- Which module signature errors can reach the permissive lockdown check, and which are returned earlier?
- What is the difference between IMA measurement and enforcing appraisal?
- Why does a TPM quote require a fresh nonce and a verifier policy?
- Does EVM authenticate all file contents merely because it protects metadata?
Answers#
- Firmware image verification and the running kernel's module verifier use different stages, configuration and keyrings. The module can also fail compatibility or later checks.
- The shown source classifies unsigned, unsupported crypto and unavailable-key cases before enforcement and lockdown; other errors including malformed or failed verification return immediately. Exact errno and policy matter.
- Measurement records evidence under policy; appraisal checks integrity metadata or signatures and can deny a covered operation when enforcement applies. One does not imply the other.
- The nonce helps the verifier detect replay of an old quote. The verifier must still trust the attestation key, interpret PCRs and log and decide which measured states satisfy policy.
- No. EVM covers configured security metadata and related attributes. Content verification belongs to the applicable appraisal or verity mechanism and its trust configuration.
Checkpoint#
Submit the three module-branch outcomes and the synthetic IMA appraisal/measurement comparison. Ready means firmware trust, module verification, lockdown and IMA/EVM are attributed to their actual stages, with limitations and no claimed module load. Retry the source branches if a signature is treated as proof of correctness. This is not certification.