fs-verity: use mempool for hash requests
Subsystems (2)
Eric Biggers
maintainerPATCH 1/1 fs-verity: use mempool for hash requests
From: Eric Biggers <[email protected]>
When initializing an fs-verity hash algorithm, also initialize a mempool that contains a single preallocated hash request object. Then replace the direct calls to ahash_request_alloc() and ahash_request_free() with allocating and freeing from this mempool.
This eliminates the possibility of the allocation failing, which is desirable for the I/O path.
This doesn't cause deadlocks because there's no case where multiple hash requests are needed at a time to make forward progress.
--- fs/verity/enable.c | 8 +-- fs/verity/fsverity_private.h | 16 ++++-- fs/verity/hash_algs.c | 98 +++++++++++++++++++++++++++--------- fs/verity/open.c | 4 +- fs/verity/verify.c | 17 +++---- 5 files changed, 97 insertions(+), 46 deletions(-)
fs/verity/enable.c +5 -3
@@ -165,9 +165,11 @@ static int build_merkle_tree(struct file *filp,return 0 ; } +/* This allocation never fails, since it's mempool-backed. */ + req =fsverity_alloc_hash_request (params->hash_alg,GFP_KERNEL ); + pending_hashes =kmalloc (params->block_size,GFP_KERNEL ); - req =ahash_request_alloc (params->hash_alg->tfm,GFP_KERNEL ); -if (!pending_hashes || !req) +if (!pending_hashes) goto out;/*
@@ -189,7 +191,7 @@ static int build_merkle_tree(struct file *filp, err =0 ; out:kfree (pending_hashes); -ahash_request_free (req); +fsverity_free_hash_request (params->hash_alg, req);return err; }
fs/verity/fsverity_private.h +11 -5
@@ -16,6 +16,7 @@#include <crypto/sha.h> #include <linux/fsverity.h> +#include <linux/mempool.h> struct ahash_request ;
@@ -37,11 +38,12 @@ struct fsverity_hash_alg {const char *name;/* crypto API name, e.g. sha256 */ unsigned int digest_size;/* digest size in bytes, e.g. 32 for SHA-256 */ unsigned int block_size;/* block size in bytes, e.g. 64 for SHA-256 */ +mempool_t req_pool;/* mempool with a preallocated hash request */ };/* Merkle tree parameters: hash algorithm, initial hash state, and topology */ struct merkle_tree_params { -const struct fsverity_hash_alg *hash_alg;/* the hash algorithm */ +struct fsverity_hash_alg *hash_alg;/* the hash algorithm */ const u8 *hashstate;/* initial hash state or NULL */ unsigned int digest_size;/* same as hash_alg->digest_size */ unsigned int block_size;/* size of data and tree blocks */
@@ -115,14 +117,18 @@ struct fsverity_signed_digest {extern struct fsverity_hash_alg fsverity_hash_algs[]; -const struct fsverity_hash_alg *fsverity_get_hash_alg (const struct inode *inode, -unsigned int num); -const u8 *fsverity_prepare_hash_state (const struct fsverity_hash_alg *alg, +struct fsverity_hash_alg *fsverity_get_hash_alg (const struct inode *inode, +unsigned int num); +struct ahash_request *fsverity_alloc_hash_request (struct fsverity_hash_alg *alg, +gfp_t gfp_flags); +void fsverity_free_hash_request (struct fsverity_hash_alg *alg, +struct ahash_request *req); +const u8 *fsverity_prepare_hash_state (struct fsverity_hash_alg *alg,const u8 *salt,size_t salt_size);int fsverity_hash_page (const struct merkle_tree_params *params,const struct inode *inode,struct ahash_request *req,struct page *page,u8 *out); -int fsverity_hash_buffer (const struct fsverity_hash_alg *alg, +int fsverity_hash_buffer (struct fsverity_hash_alg *alg,const void *data,size_t size,u8 *out);void __init fsverity_check_hash_algs (void );
fs/verity/hash_algs.c +73 -25
175 lines not on this page · raw message
fs/verity/open.c +2 -2
@@ -31,7 +31,7 @@ int fsverity_init_merkle_tree_params(struct merkle_tree_params *params,unsigned int log_blocksize, const u8 *salt, size_t salt_size) { - const struct fsverity_hash_alg *hash_alg; + struct fsverity_hash_alg *hash_alg;int err;u64 blocks;u64 offset;
@@ -127,7 +127,7 @@ int fsverity_init_merkle_tree_params(struct merkle_tree_params *params,* Compute the file measurement by hashing the fsverity_descriptor excluding the * signature and with the sig_size field set to 0. */ -static int compute_file_measurement (const struct fsverity_hash_alg *hash_alg, +static int compute_file_measurement (struct fsverity_hash_alg *hash_alg,struct fsverity_descriptor *desc,u8 *measurement) {
fs/verity/verify.c +6 -11
@@ -192,13 +192,12 @@ bool fsverity_verify_page(struct page *page)struct ahash_request *req;bool valid; - req =ahash_request_alloc (vi->tree_params.hash_alg->tfm,GFP_NOFS ); -if (unlikely (!req)) -return false; +/* This allocation never fails, since it's mempool-backed. */ + req =fsverity_alloc_hash_request (vi->tree_params.hash_alg,GFP_NOFS ); valid =verify_page (inode, vi, req, page,0 ); -ahash_request_free (req); +fsverity_free_hash_request (vi->tree_params.hash_alg, req);return valid; }
@@ -229,12 +228,8 @@ void fsverity_verify_bio(struct bio *bio)struct bvec_iter_all iter_all;unsigned long max_ra_pages =0 ; - req =ahash_request_alloc (params->hash_alg->tfm,GFP_NOFS ); -if (unlikely (!req)) { -bio_for_each_segment_all (bv, bio, iter_all) -SetPageError (bv->bv_page); -return ; - } +/* This allocation never fails, since it's mempool-backed. */ + req =fsverity_alloc_hash_request (params->hash_alg,GFP_NOFS );if (bio->bi_opf &REQ_RAHEAD ) {/*
@@ -262,7 +257,7 @@ void fsverity_verify_bio(struct bio *bio) SetPageError(page); } -ahash_request_free (req); +fsverity_free_hash_request (params->hash_alg, req); }EXPORT_SYMBOL_GPL (fsverity_verify_bio);#endif /* CONFIG_BLOCK */
Signature · 1 line
2.24.1
Quoted 7 lines · Eric Biggers
From: Eric Biggers <[email protected]>
When initializing an fs-verity hash algorithm, also initialize a mempool that contains a single preallocated hash request object. Then replace the direct calls to
ahash_request_alloc()andahash_request_free()with allocating and freeing from this mempool.
Quoted 7 lines
This eliminates the possibility of the allocation failing, which is desirable for the I/O path.
This doesn't cause deadlocks because there's no case where multiple hash requests are needed at a time to make forward progress.
Signed-off-by Eric Biggers <[email protected]>
Looks good; feel free to add:
Quoted 13 lines · Eric Biggers
From: Eric Biggers <[email protected]>
When initializing an fs-verity hash algorithm, also initialize a mempool that contains a single preallocated hash request object. Then replace the direct calls to
ahash_request_alloc()andahash_request_free()with allocating and freeing from this mempool.This eliminates the possibility of the allocation failing, which is desirable for the I/O path.
This doesn't cause deadlocks because there's no case where multiple hash requests are needed at a time to make forward progress.
Quoted 9 lines
Signed-off-by Eric Biggers <[email protected]>--- fs/verity/enable.c | 8 +-- fs/verity/fsverity_private.h | 16 ++++-- fs/verity/hash_algs.c | 98 +++++++++++++++++++++++++++--------- fs/verity/open.c | 4 +- fs/verity/verify.c | 17 +++---- 5 files changed, 97 insertions(+), 46 deletions(-)
Applied to fscrypt.git#fsverity for 5.6.
- Eric