Fixes for bpf_get_fsverity_digest()
Eric Biggers
maintainerv2 cover Fixes for bpf_get_fsverity_digest()
Two fixes for bpf_get_fsverity_digest().
Changed in v2:
- Added patch to fix silent truncation.
- Updated commit message to clarify that the size > INT_MAX case seems to be unreachable currently.
- Added Acked-bys
Eric Biggers (2):
fsverity: Fix bpf_get_fsverity_digest() dynptr assumptions
fsverity: Fix silent truncation in bpf_get_fsverity_digest()
fs/verity/measure.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
base-commit: e5fd3f514e27db1f05fbd72ba615d74941e23c51
Signature · 1 line
2.55.0
Eric Biggers
maintainerPATCH v2 1/2 fsverity: Fix bpf_get_fsverity_digest() dynptr assumptions
The BPF verifier and the dynptr abstraction ensure that the memory space referenced by a dynptr remains valid. They do not, however, provide any guarantee that the contents of the memory are stable. kfuncs are expected to remain memory-safe even if concurrent modifications occur.
bpf_get_fsverity_digest() didn't follow that: it could crash if arg->digest_size was concurrently modified.
Fix that by using the known-good value hash_alg->digest_size instead.
Also widen 'dynptr_sz' and 'out_digest_sz' to u64 to match the return type of __bpf_dynptr_size(). It doesn't appear that it can actually be more than INT_MAX currently (since __bpf_dynptr_data_rw() excludes file-based pointers), but the correct type might as well be used.
--- fs/verity/measure.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
fs/verity/measure.c +6 -4
@@ -122,11 +122,11 @@ __bpf_kfunc int bpf_get_fsverity_digest(struct file *file, const struct bpf_dynp {const struct bpf_dynptr_kern *digest_ptr = (struct bpf_dynptr_kern *)digest_p;const struct inode *inode =file_inode (file); -u32 dynptr_sz =__bpf_dynptr_size (digest_ptr); +u64 dynptr_sz =__bpf_dynptr_size (digest_ptr);struct fsverity_digest *arg;const struct fsverity_info *vi;const struct fsverity_hash_alg *hash_alg; -int out_digest_sz; +u64 out_digest_sz;if (dynptr_sz <sizeof (struct fsverity_digest ))return -EINVAL ;
@@ -150,11 +150,13 @@ __bpf_kfunc int bpf_get_fsverity_digest(struct file *file, const struct bpf_dynp out_digest_sz = dynptr_sz -sizeof (struct fsverity_digest );/* copy digest */ -memcpy (arg->digest, vi->file_digest,min_t (int, hash_alg->digest_size, out_digest_sz)); +memcpy (arg->digest, vi->file_digest, +min (hash_alg->digest_size, out_digest_sz));/* fill the extra buffer with zeros */ if (out_digest_sz > hash_alg->digest_size) -memset (arg->digest + arg->digest_size,0 , out_digest_sz - hash_alg->digest_size); +memset (arg->digest + hash_alg->digest_size,0 , + out_digest_sz - hash_alg->digest_size);return 0 ; }
Signature · 1 line
2.55.0
Eric Biggers
maintainerPATCH v2 2/2 fsverity: Fix silent truncation in bpf_get_fsverity_digest()
In reply to Eric Biggersbpf_get_fsverity_digest() silently truncates the digest if the provided buffer is too small. This is a footgun, and it doesn't match the semantics of the equivalent UAPI (FS_IOC_MEASURE_VERITY).
Change it to return -EOVERFLOW instead, matching FS_IOC_MEASURE_VERITY.
--- fs/verity/measure.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
fs/verity/measure.c +5 -4
@@ -144,14 +144,15 @@ __bpf_kfunc int bpf_get_fsverity_digest(struct file *file, const struct bpf_dynp hash_alg = vi->tree_params.hash_alg; + out_digest_sz = dynptr_sz -sizeof (struct fsverity_digest ); +if (out_digest_sz < hash_alg->digest_size) +return -EOVERFLOW ; + arg->digest_algorithm = hash_alg - fsverity_hash_algs; arg->digest_size = hash_alg->digest_size; - out_digest_sz = dynptr_sz -sizeof (struct fsverity_digest ); -/* copy digest */ -memcpy (arg->digest, vi->file_digest, -min (hash_alg->digest_size, out_digest_sz)); +memcpy (arg->digest, vi->file_digest, hash_alg->digest_size);/* fill the extra buffer with zeros */ if (out_digest_sz > hash_alg->digest_size)
Signature · 1 line
2.55.0
Re: [PATCH bpf v2 2/2] fsverity: Fix silent truncation in bpf_get_fsverity_digest()
Quoted 10 lines · Eric Biggers
bpf_get_fsverity_digest()silently truncates the digest if the provided buffer is too small. This is a footgun, and it doesn't match the semantics of the equivalent UAPI (FS_IOC_MEASURE_VERITY).Change it to return
-EOVERFLOWinstead, matchingFS_IOC_MEASURE_VERITY.Fixes 67814c00de31 ("bpf, fsverity: Add kfunc bpf_get_fsverity_digest")Signed-off-by Eric Biggers <[email protected]>
This series was applied to bpf/bpf.git (master) by Kumar Kartikeya Dwivedi <[email protected]>:
Hello:
This series was applied to bpf/bpf.git (master)
by Kumar Kartikeya Dwivedi <[email protected]>:
Quoted 9 lines · On Mon, 3 Aug 2026 11:12:30 -0700 you wrote:
Two fixes for
bpf_get_fsverity_digest().Changed in v2:
- Added patch to fix silent truncation.
- Updated commit message to clarify that the size >INT_MAXcase seems to be unreachable currently.
- Added Acked-bys[...]
Here is the summary with links:
- [bpf,v2,1/2] fsverity: Fix bpf_get_fsverity_digest() dynptr assumptions
https://git.kernel.org/bpf/bpf/c/3e8ec7c03872 - [bpf,v2,2/2] fsverity: Fix silent truncation in bpf_get_fsverity_digest() https://git.kernel.org/bpf/bpf/c/7c68ed5c5ad4
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html