Skip to contentSkip to conversation

Fixes for bpf_get_fsverity_digest()

PATCH Applied Eric Biggers 3 participants 5 messages Aug 3 – Aug 4

Subsystems (3)
lore
Share & tools
lore

Eric Biggers

author maintainer
#0 lore raw

v2 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
author maintainer
#1 lore raw

PATCH 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.

Fixes 67814c00de31 ("bpf, fsverity: Add kfunc bpf_get_fsverity_digest")
---
 fs/verity/measure.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
fs/verity/measure.c +6 -4
index cfe2d5e535f9..f8b3526af004 100644
@@ -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
author maintainer
#2 lore raw

PATCH v2 2/2 fsverity: Fix silent truncation in bpf_get_fsverity_digest()

In reply to 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 -EOVERFLOW instead, matching FS_IOC_MEASURE_VERITY.

Fixes 67814c00de31 ("bpf, fsverity: Add kfunc bpf_get_fsverity_digest")
---
 fs/verity/measure.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)
fs/verity/measure.c +5 -4
index f8b3526af004..68dfccb69772 100644
@@ -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
reviewer Acked-by on v2 2/2
#3 lore raw

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 -EOVERFLOW instead, matching FS_IOC_MEASURE_VERITY.

Fixes 67814c00de31 ("bpf, fsverity: Add kfunc bpf_get_fsverity_digest")
#4 lore raw
In reply to Eric Biggers
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_MAX case 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