A file can be stored on media that is less trusted than the process consuming it. Making that file read-only through ordinary permission bits does not prove that the bytes later returned from storage are the bytes that were approved earlier. Linux fs-verity addresses that narrower integrity boundary for supported filesystems by binding reads from an enabled file to a Merkle tree and a stable file digest.

The mechanism has two distinct security roles. The kernel verifies file data against the Merkle tree during reads. A separate policy must establish that the resulting fs-verity digest is the digest that the system intended to trust. Treating those roles as one guarantee overstates what the filesystem feature provides.

Enabling verity freezes the measured file contents

Userspace enables the feature on a regular file with FS_IOC_ENABLE_VERITY. The request specifies parameters such as the hash algorithm, block size, and optional salt. The filesystem builds the Merkle tree, stores the verity metadata in a filesystem-specific location, and marks the inode as a verity file.

The operation requires a stable input. The ioctl is issued on an O_RDONLY descriptor, the caller must have write access to the inode, and no process may hold the file open for writing while verity is being enabled. Once the operation succeeds, the file contents become read-only. Attempts to open it for writing or truncate it fail even when ordinary mode bits would otherwise permit the operation.

That immutability applies to the measured contents, not every property attached to the inode. Metadata such as ownership, mode bits, timestamps, and extended attributes can still change. The file can also be renamed, linked, or deleted. An authorization design therefore cannot equate “verity file” with an immutable pathname, immutable metadata record, or undeletable object.

The Merkle tree moves verification to the block being consumed

A conventional full-file hash requires reading the entire file to recompute the digest. fs-verity instead divides file contents into blocks and hashes them into a Merkle tree. A data block is connected through successive hash blocks to a root hash. The fs-verity file digest is derived from a descriptor that includes that root plus properties such as file size and hashing parameters.

When a protected block enters the page cache, the filesystem verifies the relevant Merkle path before exposing unverified data as an up-to-date page. Previously verified hash blocks may be cached, so verification does not require rehashing the complete file for every read.

This placement matters for memory mappings as well as explicit read calls. Verification is integrated below individual interfaces such as read(), so mmap() cannot simply bypass the check through a different userspace access path. Supported filesystems also prevent direct I/O from bypassing the verification path.

If data fails verification, ordinary reads fail with an I/O error for the affected data, while access through a memory mapping can result in SIGBUS. The mechanism is therefore enforcement on consumption, not merely a background integrity report.

A verified tree does not authenticate its own root

Merkle verification answers whether a block is consistent with the root associated with the verity file. It does not, by itself, establish that this root represents an approved publisher, package, release, or deployment state.

An attacker able to replace both a file and its untrusted integrity metadata could present a different internally consistent object unless some trusted component authenticates the expected file digest. The trust anchor must therefore sit outside the untrusted file-and-tree pair.

FS_IOC_MEASURE_VERITY exposes the digest that the kernel is enforcing for a verity file. Trusted userspace can compare that digest with an authenticated manifest or verify a digital signature over it. Linux can also integrate fs-verity digests with policy mechanisms such as IMA or IPE. Built-in fs-verity signatures are another option when the kernel and deployment policy are configured for that model.

The security boundary is explicit: Merkle verification protects consistency between reads and the enforced digest; authentication policy assigns authority to a particular digest.

Read-only content is narrower than object identity

The digest identifies protected file contents and the verity descriptor parameters used to derive it. It is not a general-purpose signature over all filesystem metadata.

Changing an owner, permission mode, timestamp, pathname, or unrelated extended attribute does not change the protected content digest. A system that grants authority based on those properties needs separate checks for them. Conversely, a content-addressed deployment can use the digest as a stable content identity even when the pathname changes.

This distinction also affects replacement attacks. A directory entry that once referred to a trusted verity file can later refer to another inode after deletion and recreation if the surrounding namespace permits that operation. Code that requires a particular artifact must authenticate the digest of the object it actually opens, rather than assuming that a familiar pathname permanently identifies the approved inode.

fs-verity therefore complements pathname authorization and directory permissions; it does not replace them.

Signature enforcement is a policy layer, not an automatic property

Kernel support can verify a built-in PKCS#7 signature associated with a verity file when the relevant configuration is enabled and trusted certificates are present in the fs-verity keyring. A system can also require signatures for verity files through the corresponding sysctl.

Even then, signature verification does not automatically create a complete policy saying that every executable or every file in a directory must use fs-verity. A non-verity file exists outside that property unless another trusted component or policy rejects it.

This is a common boundary error in integrity designs: a mechanism can validate an object strongly once the object participates in the mechanism, while leaving object selection to another layer. IMA appraisal, IPE policy, or trusted application logic can supply that selection rule depending on the deployment.

A signature also authenticates according to the keys accepted by the policy. Key provisioning, rotation, revocation, and the decision about which files require authenticated digests remain operational security concerns beyond Merkle verification itself.

Filesystem support determines the storage and access contract

fs-verity is a support layer used by filesystems rather than a format that every mounted filesystem automatically implements. Current kernel documentation describes support in ext4, f2fs, and btrfs, with filesystem-specific storage for the tree and descriptor.

The filesystem and kernel must both expose the feature. Enabling verity can fail when kernel support is absent, when the filesystem does not implement it, or when filesystem feature state does not permit it. Software that depends on the property must treat successful enablement or measurement as part of its deployment contract rather than infer support from the kernel version alone.

Copying a verity file through an ordinary file-copy operation also does not imply that the destination retains verity state. The copied bytes can be identical while the destination is a normal writable file with no associated Merkle-tree enforcement. Artifact pipelines that require fs-verity need to establish the property at the destination and then authenticate the resulting digest.

Integrity failure changes application failure modes

Because verification occurs on reads, storage corruption or tampering can surface after a file has already been opened successfully. An application cannot assume that a successful open() guarantees every later page will remain readable.

For buffered reads, the application may receive an I/O error when a corrupt block is reached. For memory-mapped access, the process can receive SIGBUS. Long-lived services that map protected databases, indexes, executables, or package payloads need a failure policy that accounts for integrity errors appearing at access time.

This behavior is a deliberate consequence of block-level verification. It permits large files to be consumed without hashing every byte before first use, but it places integrity failure on the data-access path.

The durable boundary is digest plus enforcement plus selection

fs-verity provides a kernel-enforced relation between read-only file contents and a Merkle-tree-backed digest. That relation is valuable precisely because it is narrower than a general trust decision.

A deployment obtains a stronger authenticity property only when three pieces meet: the filesystem enforces verified reads, a trusted mechanism authenticates the expected digest, and object-selection policy rejects artifacts that do not satisfy that requirement. Omitting the second piece leaves a verified but unauthenticated root. Omitting the third can leave unprotected replacement objects outside the verity policy.

The resulting architecture separates storage integrity from publisher or deployment authority. That separation makes the trust boundary inspectable: the kernel verifies bytes against the file digest, while policy decides which digest is permitted to carry authority.