Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fsverity: improve documentation for builtin signature support

fsverity builtin signatures (CONFIG_FS_VERITY_BUILTIN_SIGNATURES) aren't
the only way to do signatures with fsverity, and they have some major
limitations. Yet, more users have tried to use them, e.g. recently by
https://github.com/ostreedev/ostree/pull/2640. In most cases this seems
to be because users aren't sufficiently familiar with the limitations of
this feature and what the alternatives are.

Therefore, make some updates to the documentation to try to clarify the
properties of this feature and nudge users in the right direction.

Note that the Integrity Policy Enforcement (IPE) LSM, which is not yet
upstream, is planned to use the builtin signatures. (This differs from
IMA, which uses its own signature mechanism.) For that reason, my
earlier patch "fsverity: mark builtin signatures as deprecated"
(https://lore.kernel.org/r/20221208033548.122704-1-ebiggers@kernel.org),
which marked builtin signatures as "deprecated", was controversial.

This patch therefore stops short of marking the feature as deprecated.
I've also revised the language to focus on better explaining the feature
and what its alternatives are.

Link: https://lore.kernel.org/r/20230620041937.5809-1-ebiggers@kernel.org
Reviewed-by: Colin Walters <walters@verbum.org>
Reviewed-by: Luca Boccassi <bluca@debian.org>
Signed-off-by: Eric Biggers <ebiggers@google.com>

+146 -78
+123 -63
Documentation/filesystems/fsverity.rst
··· 38 38 Use cases 39 39 ========= 40 40 41 - By itself, the base fs-verity feature only provides integrity 42 - protection, i.e. detection of accidental (non-malicious) corruption. 41 + By itself, fs-verity only provides integrity protection, i.e. 42 + detection of accidental (non-malicious) corruption. 43 43 44 44 However, because fs-verity makes retrieving the file hash extremely 45 45 efficient, it's primarily meant to be used as a tool to support 46 46 authentication (detection of malicious modifications) or auditing 47 47 (logging file hashes before use). 48 - 49 - Trusted userspace code (e.g. operating system code running on a 50 - read-only partition that is itself authenticated by dm-verity) can 51 - authenticate the contents of an fs-verity file by using the 52 - `FS_IOC_MEASURE_VERITY`_ ioctl to retrieve its hash, then verifying a 53 - digital signature of it. 54 48 55 49 A standard file hash could be used instead of fs-verity. However, 56 50 this is inefficient if the file is large and only a small portion may ··· 63 69 must live on a read-write filesystem because they are independently 64 70 updated and potentially user-installed, so dm-verity cannot be used. 65 71 66 - The base fs-verity feature is a hashing mechanism only; actually 67 - authenticating the files may be done by: 72 + fs-verity does not mandate a particular scheme for authenticating its 73 + file hashes. (Similarly, dm-verity does not mandate a particular 74 + scheme for authenticating its block device root hashes.) Options for 75 + authenticating fs-verity file hashes include: 68 76 69 - * Userspace-only 77 + - Trusted userspace code. Often, the userspace code that accesses 78 + files can be trusted to authenticate them. Consider e.g. an 79 + application that wants to authenticate data files before using them, 80 + or an application loader that is part of the operating system (which 81 + is already authenticated in a different way, such as by being loaded 82 + from a read-only partition that uses dm-verity) and that wants to 83 + authenticate applications before loading them. In these cases, this 84 + trusted userspace code can authenticate a file's contents by 85 + retrieving its fs-verity digest using `FS_IOC_MEASURE_VERITY`_, then 86 + verifying a signature of it using any userspace cryptographic 87 + library that supports digital signatures. 70 88 71 - * Builtin signature verification + userspace policy 89 + - Integrity Measurement Architecture (IMA). IMA supports fs-verity 90 + file digests as an alternative to its traditional full file digests. 91 + "IMA appraisal" enforces that files contain a valid, matching 92 + signature in their "security.ima" extended attribute, as controlled 93 + by the IMA policy. For more information, see the IMA documentation. 72 94 73 - fs-verity optionally supports a simple signature verification 74 - mechanism where users can configure the kernel to require that 75 - all fs-verity files be signed by a key loaded into a keyring; 76 - see `Built-in signature verification`_. 77 - 78 - * Integrity Measurement Architecture (IMA) 79 - 80 - IMA supports including fs-verity file digests and signatures in the 81 - IMA measurement list and verifying fs-verity based file signatures 82 - stored as security.ima xattrs, based on policy. 83 - 95 + - Trusted userspace code in combination with `Built-in signature 96 + verification`_. This approach should be used only with great care. 84 97 85 98 User API 86 99 ======== ··· 112 111 }; 113 112 114 113 This structure contains the parameters of the Merkle tree to build for 115 - the file, and optionally contains a signature. It must be initialized 116 - as follows: 114 + the file. It must be initialized as follows: 117 115 118 116 - ``version`` must be 1. 119 117 - ``hash_algorithm`` must be the identifier for the hash algorithm to ··· 129 129 file or device. Currently the maximum salt size is 32 bytes. 130 130 - ``salt_ptr`` is the pointer to the salt, or NULL if no salt is 131 131 provided. 132 - - ``sig_size`` is the size of the signature in bytes, or 0 if no 133 - signature is provided. Currently the signature is (somewhat 134 - arbitrarily) limited to 16128 bytes. See `Built-in signature 135 - verification`_ for more information. 136 - - ``sig_ptr`` is the pointer to the signature, or NULL if no 137 - signature is provided. 132 + - ``sig_size`` is the size of the builtin signature in bytes, or 0 if no 133 + builtin signature is provided. Currently the builtin signature is 134 + (somewhat arbitrarily) limited to 16128 bytes. 135 + - ``sig_ptr`` is the pointer to the builtin signature, or NULL if no 136 + builtin signature is provided. A builtin signature is only needed 137 + if the `Built-in signature verification`_ feature is being used. It 138 + is not needed for IMA appraisal, and it is not needed if the file 139 + signature is being handled entirely in userspace. 138 140 - All reserved fields must be zeroed. 139 141 140 142 FS_IOC_ENABLE_VERITY causes the filesystem to build a Merkle tree for ··· 160 158 FS_IOC_ENABLE_VERITY can fail with the following errors: 161 159 162 160 - ``EACCES``: the process does not have write access to the file 163 - - ``EBADMSG``: the signature is malformed 161 + - ``EBADMSG``: the builtin signature is malformed 164 162 - ``EBUSY``: this ioctl is already running on the file 165 163 - ``EEXIST``: the file already has verity enabled 166 164 - ``EFAULT``: the caller provided inaccessible memory ··· 170 168 reserved bits are set; or the file descriptor refers to neither a 171 169 regular file nor a directory. 172 170 - ``EISDIR``: the file descriptor refers to a directory 173 - - ``EKEYREJECTED``: the signature doesn't match the file 174 - - ``EMSGSIZE``: the salt or signature is too long 175 - - ``ENOKEY``: the fs-verity keyring doesn't contain the certificate 176 - needed to verify the signature 171 + - ``EKEYREJECTED``: the builtin signature doesn't match the file 172 + - ``EMSGSIZE``: the salt or builtin signature is too long 173 + - ``ENOKEY``: the ".fs-verity" keyring doesn't contain the certificate 174 + needed to verify the builtin signature 177 175 - ``ENOPKG``: fs-verity recognizes the hash algorithm, but it's not 178 176 available in the kernel's crypto API as currently configured (e.g. 179 177 for SHA-512, missing CONFIG_CRYPTO_SHA512). ··· 182 180 support; or the filesystem superblock has not had the 'verity' 183 181 feature enabled on it; or the filesystem does not support fs-verity 184 182 on this file. (See `Filesystem support`_.) 185 - - ``EPERM``: the file is append-only; or, a signature is required and 186 - one was not provided. 183 + - ``EPERM``: the file is append-only; or, a builtin signature is 184 + required and one was not provided. 187 185 - ``EROFS``: the filesystem is read-only 188 186 - ``ETXTBSY``: someone has the file open for writing. This can be the 189 187 caller's file descriptor, another open file descriptor, or the file ··· 272 270 - ``FS_VERITY_METADATA_TYPE_DESCRIPTOR`` reads the fs-verity 273 271 descriptor. See `fs-verity descriptor`_. 274 272 275 - - ``FS_VERITY_METADATA_TYPE_SIGNATURE`` reads the signature which was 276 - passed to FS_IOC_ENABLE_VERITY, if any. See `Built-in signature 277 - verification`_. 273 + - ``FS_VERITY_METADATA_TYPE_SIGNATURE`` reads the builtin signature 274 + which was passed to FS_IOC_ENABLE_VERITY, if any. See `Built-in 275 + signature verification`_. 278 276 279 277 The semantics are similar to those of ``pread()``. ``offset`` 280 278 specifies the offset in bytes into the metadata item to read from, and ··· 301 299 overflowed 302 300 - ``ENODATA``: the file is not a verity file, or 303 301 FS_VERITY_METADATA_TYPE_SIGNATURE was requested but the file doesn't 304 - have a built-in signature 302 + have a builtin signature 305 303 - ``ENOTTY``: this type of filesystem does not implement fs-verity, or 306 304 this ioctl is not yet implemented on it 307 305 - ``EOPNOTSUPP``: the kernel was not configured with fs-verity ··· 349 347 with EIO (for read()) or SIGBUS (for mmap() reads). 350 348 351 349 - If the sysctl "fs.verity.require_signatures" is set to 1 and the 352 - file is not signed by a key in the fs-verity keyring, then opening 353 - the file will fail. See `Built-in signature verification`_. 350 + file is not signed by a key in the ".fs-verity" keyring, then 351 + opening the file will fail. See `Built-in signature verification`_. 354 352 355 353 Direct access to the Merkle tree is not supported. Therefore, if a 356 354 verity file is copied, or is backed up and restored, then it will lose ··· 435 433 Built-in signature verification 436 434 =============================== 437 435 438 - With CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y, fs-verity supports putting 439 - a portion of an authentication policy (see `Use cases`_) in the 440 - kernel. Specifically, it adds support for: 436 + CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y adds supports for in-kernel 437 + verification of fs-verity builtin signatures. 441 438 442 - 1. At fs-verity module initialization time, a keyring ".fs-verity" is 443 - created. The root user can add trusted X.509 certificates to this 444 - keyring using the add_key() system call, then (when done) 445 - optionally use keyctl_restrict_keyring() to prevent additional 446 - certificates from being added. 439 + **IMPORTANT**! Please take great care before using this feature. 440 + It is not the only way to do signatures with fs-verity, and the 441 + alternatives (such as userspace signature verification, and IMA 442 + appraisal) can be much better. It's also easy to fall into a trap 443 + of thinking this feature solves more problems than it actually does. 444 + 445 + Enabling this option adds the following: 446 + 447 + 1. At boot time, the kernel creates a keyring named ".fs-verity". The 448 + root user can add trusted X.509 certificates to this keyring using 449 + the add_key() system call. 447 450 448 451 2. `FS_IOC_ENABLE_VERITY`_ accepts a pointer to a PKCS#7 formatted 449 452 detached signature in DER format of the file's fs-verity digest. 450 - On success, this signature is persisted alongside the Merkle tree. 451 - Then, any time the file is opened, the kernel will verify the 453 + On success, the ioctl persists the signature alongside the Merkle 454 + tree. Then, any time the file is opened, the kernel verifies the 452 455 file's actual digest against this signature, using the certificates 453 456 in the ".fs-verity" keyring. 454 457 ··· 461 454 When set to 1, the kernel requires that all verity files have a 462 455 correctly signed digest as described in (2). 463 456 464 - fs-verity file digests must be signed in the following format, which 465 - is similar to the structure used by `FS_IOC_MEASURE_VERITY`_:: 457 + The data that the signature as described in (2) must be a signature of 458 + is the fs-verity file digest in the following format:: 466 459 467 460 struct fsverity_formatted_digest { 468 461 char magic[8]; /* must be "FSVerity" */ ··· 471 464 __u8 digest[]; 472 465 }; 473 466 474 - fs-verity's built-in signature verification support is meant as a 475 - relatively simple mechanism that can be used to provide some level of 476 - authenticity protection for verity files, as an alternative to doing 477 - the signature verification in userspace or using IMA-appraisal. 478 - However, with this mechanism, userspace programs still need to check 479 - that the verity bit is set, and there is no protection against verity 480 - files being swapped around. 467 + That's it. It should be emphasized again that fs-verity builtin 468 + signatures are not the only way to do signatures with fs-verity. See 469 + `Use cases`_ for an overview of ways in which fs-verity can be used. 470 + fs-verity builtin signatures have some major limitations that should 471 + be carefully considered before using them: 472 + 473 + - Builtin signature verification does *not* make the kernel enforce 474 + that any files actually have fs-verity enabled. Thus, it is not a 475 + complete authentication policy. Currently, if it is used, the only 476 + way to complete the authentication policy is for trusted userspace 477 + code to explicitly check whether files have fs-verity enabled with a 478 + signature before they are accessed. (With 479 + fs.verity.require_signatures=1, just checking whether fs-verity is 480 + enabled suffices.) But, in this case the trusted userspace code 481 + could just store the signature alongside the file and verify it 482 + itself using a cryptographic library, instead of using this feature. 483 + 484 + - A file's builtin signature can only be set at the same time that 485 + fs-verity is being enabled on the file. Changing or deleting the 486 + builtin signature later requires re-creating the file. 487 + 488 + - Builtin signature verification uses the same set of public keys for 489 + all fs-verity enabled files on the system. Different keys cannot be 490 + trusted for different files; each key is all or nothing. 491 + 492 + - The sysctl fs.verity.require_signatures applies system-wide. 493 + Setting it to 1 only works when all users of fs-verity on the system 494 + agree that it should be set to 1. This limitation can prevent 495 + fs-verity from being used in cases where it would be helpful. 496 + 497 + - Builtin signature verification can only use signature algorithms 498 + that are supported by the kernel. For example, the kernel does not 499 + yet support Ed25519, even though this is often the signature 500 + algorithm that is recommended for new cryptographic designs. 501 + 502 + - fs-verity builtin signatures are in PKCS#7 format, and the public 503 + keys are in X.509 format. These formats are commonly used, 504 + including by some other kernel features (which is why the fs-verity 505 + builtin signatures use them), and are very feature rich. 506 + Unfortunately, history has shown that code that parses and handles 507 + these formats (which are from the 1990s and are based on ASN.1) 508 + often has vulnerabilities as a result of their complexity. This 509 + complexity is not inherent to the cryptography itself. 510 + 511 + fs-verity users who do not need advanced features of X.509 and 512 + PKCS#7 should strongly consider using simpler formats, such as plain 513 + Ed25519 keys and signatures, and verifying signatures in userspace. 514 + 515 + fs-verity users who choose to use X.509 and PKCS#7 anyway should 516 + still consider that verifying those signatures in userspace is more 517 + flexible (for other reasons mentioned earlier in this document) and 518 + eliminates the need to enable CONFIG_FS_VERITY_BUILTIN_SIGNATURES 519 + and its associated increase in kernel attack surface. In some cases 520 + it can even be necessary, since advanced X.509 and PKCS#7 features 521 + do not always work as intended with the kernel. For example, the 522 + kernel does not check X.509 certificate validity times. 523 + 524 + Note: IMA appraisal, which supports fs-verity, does not use PKCS#7 525 + for its signatures, so it partially avoids the issues discussed 526 + here. IMA appraisal does use X.509. 481 527 482 528 Filesystem support 483 529 ==================
+8 -8
fs/verity/Kconfig
··· 39 39 depends on FS_VERITY 40 40 select SYSTEM_DATA_VERIFICATION 41 41 help 42 - Support verifying signatures of verity files against the X.509 43 - certificates that have been loaded into the ".fs-verity" 44 - kernel keyring. 42 + This option adds support for in-kernel verification of 43 + fs-verity builtin signatures. 45 44 46 - This is meant as a relatively simple mechanism that can be 47 - used to provide an authenticity guarantee for verity files, as 48 - an alternative to IMA appraisal. Userspace programs still 49 - need to check that the verity bit is set in order to get an 50 - authenticity guarantee. 45 + Please take great care before using this feature. It is not 46 + the only way to do signatures with fs-verity, and the 47 + alternatives (such as userspace signature verification, and 48 + IMA appraisal) can be much better. For details about the 49 + limitations of this feature, see 50 + Documentation/filesystems/fsverity.rst. 51 51 52 52 If unsure, say N.
+1 -1
fs/verity/enable.c
··· 208 208 } 209 209 desc->salt_size = arg->salt_size; 210 210 211 - /* Get the signature if the user provided one */ 211 + /* Get the builtin signature if the user provided one */ 212 212 if (arg->sig_size && 213 213 copy_from_user(desc->signature, u64_to_user_ptr(arg->sig_ptr), 214 214 arg->sig_size)) {
+4 -4
fs/verity/open.c
··· 156 156 157 157 /* 158 158 * Compute the file digest by hashing the fsverity_descriptor excluding the 159 - * signature and with the sig_size field set to 0. 159 + * builtin signature and with the sig_size field set to 0. 160 160 */ 161 161 static int compute_file_digest(const struct fsverity_hash_alg *hash_alg, 162 162 struct fsverity_descriptor *desc, ··· 174 174 175 175 /* 176 176 * Create a new fsverity_info from the given fsverity_descriptor (with optional 177 - * appended signature), and check the signature if present. The 177 + * appended builtin signature), and check the signature if present. The 178 178 * fsverity_descriptor must have already undergone basic validation. 179 179 */ 180 180 struct fsverity_info *fsverity_create_info(const struct inode *inode, ··· 319 319 } 320 320 321 321 /* 322 - * Read the inode's fsverity_descriptor (with optional appended signature) from 323 - * the filesystem, and do basic validation of it. 322 + * Read the inode's fsverity_descriptor (with optional appended builtin 323 + * signature) from the filesystem, and do basic validation of it. 324 324 */ 325 325 int fsverity_get_descriptor(struct inode *inode, 326 326 struct fsverity_descriptor **desc_ret)
+2 -2
fs/verity/read_metadata.c
··· 105 105 if (res) 106 106 return res; 107 107 108 - /* don't include the signature */ 108 + /* don't include the builtin signature */ 109 109 desc_size = offsetof(struct fsverity_descriptor, signature); 110 110 desc->sig_size = 0; 111 111 ··· 131 131 } 132 132 133 133 /* 134 - * Include only the signature. Note that fsverity_get_descriptor() 134 + * Include only the builtin signature. fsverity_get_descriptor() 135 135 * already verified that sig_size is in-bounds. 136 136 */ 137 137 res = fsverity_read_buffer(buf, offset, length, desc->signature,
+8
fs/verity/signature.c
··· 5 5 * Copyright 2019 Google LLC 6 6 */ 7 7 8 + /* 9 + * This file implements verification of fs-verity builtin signatures. Please 10 + * take great care before using this feature. It is not the only way to do 11 + * signatures with fs-verity, and the alternatives (such as userspace signature 12 + * verification, and IMA appraisal) can be much better. For details about the 13 + * limitations of this feature, see Documentation/filesystems/fsverity.rst. 14 + */ 15 + 8 16 #include "fsverity_private.h" 9 17 10 18 #include <linux/cred.h>