Hệ điều hành · 05/10/2026

Practical fs-verity: Protecting Read-Only File Integrity on Linux

A checksum stored next to a file detects changes only when a process deliberately rehashes the whole file. fs-verity moves verification into the filesystem: after it is enabled, file contents become immutable, are bound to a Merkle tree, and every block brought into the page cache must pass an integrity check.

fs-verity thực chiến: Bảo vệ tính toàn vẹn file chỉ-đọc trên Linux

A checksum stored next to a file detects changes only when a process deliberately rehashes the whole file. fs-verity moves verification into the filesystem: after it is enabled, file contents become immutable, are bound to a Merkle tree, and every block brought into the page cache must pass an integrity check.

This guide deploys fs-verity for artifacts, AI models, binaries, and large data files that live on a writable filesystem. It follows the Linux kernel fs-verity documentation and fsverity-utils, with emphasis on security boundaries, atomic release workflow, digest trust, and production operations.

1. What does fs-verity actually protect?

When verity is enabled on a regular file, the filesystem builds a Merkle tree from its contents and stores metadata in a filesystem-specific form. The file becomes read-only. For later reads, including read(), pread(), and mmap(), the kernel verifies each required block through its hash path to the root; corrupted data is not returned to the application.

The measured fs-verity digest identifies the content whose verification the kernel enforces, but it is not the same as a conventional full-file SHA-256 checksum. It incorporates the fs-verity descriptor and Merkle-tree format. Do not compare fsverity measure output directly with sha256sum.

2. Integrity is not automatically authenticity

Running fsverity enable alone detects accidental corruption. An attacker able to replace the entire file and enable verity again can create a different, internally valid digest. To detect malicious replacement, a consumer must compare the measured digest with a value from an independent trust source or use a suitable signature and policy-enforcement design.

The trust anchor may be a signed release manifest, protected control-plane metadata, a trusted userspace loader, IMA appraisal, or another signature design. Kernel documentation notes that built-in PKCS#7 signatures are not the only option and have important limitations; do not enable them merely to claim that files are signed.

3. fs-verity versus dm-verity, IMA, and checksums

MechanismScopeStrengthYou still design
sha256sumOne pass over a fileSimple and portableWhen to read the whole file and how to trust the expected value
fs-verityIndividual read-only filePer-block read-time verification and fast digest retrievalDigest trust and policy requiring verity
dm-verityRead-only block device or filesystem imageProtects a complete imageIndependent updates do not fit naturally
IMASystem-wide policyMeasurement, audit, or appraisal by policyPolicy, keys, and a trusted boot chain

fs-verity does not replace dm-verity. Use dm-verity for an immutable root or image and fs-verity when individual artifacts must update independently on a read-write volume.

4. Check kernel and filesystem prerequisites

The kernel needs CONFIG_FS_VERITY, and the filesystem must support and enable its corresponding feature. Current kernel documentation lists ext4, f2fs, and btrfs; actual availability depends on the kernel, filesystem tools, and distribution versions.

grep FS_VERITY /boot/config-$(uname -r)
findmnt -no SOURCE,FSTYPE,OPTIONS /srv/artifacts
fsverity --version

# For ext4: replace the device with verified findmnt output
sudo tune2fs -l /dev/mapper/data | grep 'Filesystem features'

A new ext4 filesystem can be created with mkfs.ext4 -O verity. Enabling a feature on an existing volume is a filesystem change: take a backup, identify the exact device, follow the distribution's e2fsprogs guidance, and use a tested maintenance workflow. Never paste a tune2fs command into production before the volume and rollback plan are clear.

5. A minimal experiment

sudo apt install fsverity

cp release/model-v42.bin /srv/artifacts/.model-v42.bin.staging
sync
fsverity digest /srv/artifacts/.model-v42.bin.staging
sudo fsverity enable /srv/artifacts/.model-v42.bin.staging
sudo fsverity measure /srv/artifacts/.model-v42.bin.staging

digest computes the expected digest in userspace; enable requires stable contents with no writable file descriptors or mappings; measure retrieves the digest enforced by the kernel. Record the algorithm together with the digest rather than storing an unlabeled hexadecimal string.

After enable succeeds, file contents cannot be modified and verity cannot be disabled for that inode. This is a one-way transition. Directory permissions may still allow deletion or rename, so an immutable file does not mean that its pathname cannot be replaced.

6. Publish artifacts atomically

  1. Download the artifact into a staging file on the destination filesystem.
  2. Check size, pipeline checksum, and signature or attestation before enabling verity.
  3. fsync when durability is required, then close all writers.
  4. Enable fs-verity and measure the resulting digest.
  5. Compare the digest exactly with the trusted manifest.
  6. Rename staging to a versioned name atomically on the same filesystem.
  7. Switch a separate current symlink or metadata pointer, then health-check consumers.
sudo mv /srv/artifacts/.model-v42.bin.staging \
  /srv/artifacts/model-v42.bin

sudo ln -sfn model-v42.bin /srv/artifacts/model-current.next
sudo mv -Tf /srv/artifacts/model-current.next \
  /srv/artifacts/model-current

Never update a verity file in place. Create and verify a new inode or version, then switch the pointer. Retain the previous version for the rollback window instead of trying to undo verity.

7. Design the manifest and trust path

{
  "name": "model-v42.bin",
  "size": 734003200,
  "fsverity_algorithm": "sha256",
  "fsverity_digest": "<hex digest from approved pipeline>",
  "release": "42",
  "created_at": "2026-10-05T09:00:00Z"
}

Authenticate the manifest independently with a release signature, controlled metadata store, or another trusted channel. If an unsigned manifest and artifact share a directory and write authority, an attacker can replace both.

A trusted consumer should measure immediately before accepting a version, enforce name, size, and version policy, and then use the opened file descriptor to reduce time-of-check/time-of-use gaps. A pathname can change between lookups even though a verity inode's contents cannot.

8. File and directory permissions still matter

fs-verity protects file data blocks. It does not automatically protect the filename, owner, mode, every extended attribute, adjacent symlinks, or directory entries. Restrict release-directory writes, separate deployment identity from runtime identity, and do not let the service replace its own current pointer.

Root or an actor with strong mount and storage privileges can still delete or replace a file or cause denial of service. fs-verity turns silent content modification into a detectable failure; it does not provide availability, access control, or sandboxing.

9. Responding to corrupted data

Verification occurs as blocks are read. A file may measure successfully while an unread block is damaged; the error appears only when a workload reaches that block. Applications must handle I/O failure explicitly rather than retrying forever or consuming partial data.

journalctl -k --since today | grep -i verity
fsverity measure /srv/artifacts/model-v42.bin

# Use filesystem or storage scrubbing where supported
# A controlled sequential-read job can exercise all file blocks

A safe response normally quarantines the artifact, redirects consumers to a known-good version, preserves device and filesystem evidence, and restores from a trusted source. Do not attempt to repair a few bytes in an inode with verity enabled.

10. Backup, restore, and copying

A content copy may retain the same conventional checksum without retaining fs-verity state or metadata. Preservation depends on the tool, filesystem, and backup format. Treat restoration as a new artifact workflow: restore to staging, validate checksum and signature, enable verity, measure, and compare with the manifest.

Run restore tests on the real destination filesystem. Testing only that tar or rsync returns the correct byte count is insufficient; verify fsverity measure, consumer policy, and behavior after reboot or remount.

11. Cost and capacity planning

Enable must read the file and construct a Merkle tree, consuming I/O, CPU, and metadata space. For large files, do this in staging before serving traffic. Read-time verification generally follows blocks actually paged in, but hashing and hash-block reads still have a cost.

Benchmark the real access pattern: cold cache, warm cache, random mmap, concurrent startup, and slow storage. Track enable duration, read latency, page faults, I/O, CPU, and integrity failures. Do not extrapolate production overhead from one cat of a small file.

12. Testing and rollout

Do not modify raw blocks of a production volume to test corruption. Kernel documentation recommends xfstests for filesystem testing; use a dedicated lab or disposable image for fault injection. Application tests can simulate read failures and digest mismatch to prove fail-closed behavior, rollback, and alerting.

Roll out in layers: one noncritical artifact, a canary host group, and then wider deployment. Validate kernel and filesystem support, boot paths, backup agents, scanners, deployment tools, and container bind mounts. A tool that writes metadata or replaces files in place may fail after verity is enabled.

Production checklist

  • The use case is a versioned read-only file, not mutable data.
  • Kernel, filesystem, feature flags, and fsverity-utils are verified on actual hosts.
  • The artifact is staged and every writer is closed before enable.
  • The fs-verity digest is checked against an independently trusted manifest.
  • Updates use a new inode and atomic rename or pointer switch; the old version remains available for rollback.
  • Directory permissions prevent out-of-process pathname replacement.
  • The application fails closed on read errors or digest mismatch.
  • Backup and restore tests include re-enabling and measuring on the destination filesystem.
  • Canaries measure latency, CPU, I/O, and kernel errors before wider rollout.
  • The runbook distinguishes corruption, replacement, absence, and storage failure.

Conclusion

fs-verity fits large artifacts that must live on a writable filesystem while each released version remains immutable and verified during reads. The Merkle tree makes verification efficient; it does not create trust by itself. A complete production design needs an authenticated digest, directory permissions, new-inode publishing, versioned rollback, restore tests, and a fail-closed consumer. With those boundaries explicit, fs-verity is a strong integrity layer rather than a checkbox that creates false confidence.

Discussion

Comments 0

Sign in to comment

You need an account to join the discussion and reply to other readers.

Sign inRegister

No comments yet. Be the first to share your thoughts.