1010#include <linux/bio.h>
1111#include <linux/export.h>
1212
13+ #define FS_VERITY_MAX_PENDING_BLOCKS 2
14+
15+ struct fsverity_pending_block {
16+ const void * data ;
17+ u64 pos ;
18+ u8 real_hash [FS_VERITY_MAX_DIGEST_SIZE ];
19+ };
20+
21+ struct fsverity_verification_context {
22+ struct inode * inode ;
23+ struct fsverity_info * vi ;
24+ unsigned long max_ra_pages ;
25+
26+ /*
27+ * This is the queue of data blocks that are pending verification. When
28+ * the crypto layer supports interleaved hashing, we allow multiple
29+ * blocks to be queued up in order to utilize it. This can improve
30+ * performance significantly vs. sequential hashing of each block.
31+ */
32+ int num_pending ;
33+ int max_pending ;
34+ struct fsverity_pending_block
35+ pending_blocks [FS_VERITY_MAX_PENDING_BLOCKS ];
36+ };
37+
1338static struct workqueue_struct * fsverity_read_workqueue ;
1439
1540/*
@@ -79,7 +104,7 @@ static bool is_hash_block_verified(struct fsverity_info *vi, struct page *hpage,
79104}
80105
81106/*
82- * Verify a single data block against the file's Merkle tree.
107+ * Verify the hash of a single data block against the file's Merkle tree.
83108 *
84109 * In principle, we need to verify the entire path to the root node. However,
85110 * for efficiency the filesystem may cache the hash blocks. Therefore we need
@@ -88,10 +113,11 @@ static bool is_hash_block_verified(struct fsverity_info *vi, struct page *hpage,
88113 *
89114 * Return: %true if the data block is valid, else %false.
90115 */
91- static bool
92- verify_data_block ( struct inode * inode , struct fsverity_info * vi ,
93- const void * data , u64 data_pos , unsigned long max_ra_pages )
116+ static bool verify_data_block ( struct inode * inode , struct fsverity_info * vi ,
117+ const struct fsverity_pending_block * dblock ,
118+ unsigned long max_ra_pages )
94119{
120+ const u64 data_pos = dblock -> pos ;
95121 const struct merkle_tree_params * params = & vi -> tree_params ;
96122 const unsigned int hsize = params -> digest_size ;
97123 int level ;
@@ -115,8 +141,12 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi,
115141 */
116142 u64 hidx = data_pos >> params -> log_blocksize ;
117143
118- /* Up to 1 + FS_VERITY_MAX_LEVELS pages may be mapped at once */
119- BUILD_BUG_ON (1 + FS_VERITY_MAX_LEVELS > KM_MAX_IDX );
144+ /*
145+ * Up to FS_VERITY_MAX_PENDING_BLOCKS + FS_VERITY_MAX_LEVELS pages may
146+ * be mapped at once.
147+ */
148+ static_assert (FS_VERITY_MAX_PENDING_BLOCKS + FS_VERITY_MAX_LEVELS <=
149+ KM_MAX_IDX );
120150
121151 if (unlikely (data_pos >= inode -> i_size )) {
122152 /*
@@ -127,7 +157,7 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi,
127157 * any part past EOF should be all zeroes. Therefore, we need
128158 * to verify that any data blocks fully past EOF are all zeroes.
129159 */
130- if (memchr_inv (data , 0 , params -> block_size )) {
160+ if (memchr_inv (dblock -> data , 0 , params -> block_size )) {
131161 fsverity_err (inode ,
132162 "FILE CORRUPTED! Data past EOF is not zeroed" );
133163 return false;
@@ -202,7 +232,7 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi,
202232 unsigned long hblock_idx = hblocks [level - 1 ].index ;
203233 unsigned int hoffset = hblocks [level - 1 ].hoffset ;
204234
205- fsverity_hash_block (params , inode , haddr , real_hash );
235+ fsverity_hash_block (params , haddr , real_hash );
206236 if (memcmp (want_hash , real_hash , hsize ) != 0 )
207237 goto corrupted ;
208238 /*
@@ -220,18 +250,18 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi,
220250 put_page (hpage );
221251 }
222252
223- /* Finally, verify the data block. */
224- fsverity_hash_block (params , inode , data , real_hash );
225- if (memcmp (want_hash , real_hash , hsize ) != 0 )
253+ /* Finally, verify the hash of the data block. */
254+ if (memcmp (want_hash , dblock -> real_hash , hsize ) != 0 )
226255 goto corrupted ;
227256 return true;
228257
229258corrupted :
230- fsverity_err (inode ,
231- "FILE CORRUPTED! pos=%llu, level=%d, want_hash=%s:%*phN, real_hash=%s:%*phN" ,
232- data_pos , level - 1 ,
233- params -> hash_alg -> name , hsize , want_hash ,
234- params -> hash_alg -> name , hsize , real_hash );
259+ fsverity_err (
260+ inode ,
261+ "FILE CORRUPTED! pos=%llu, level=%d, want_hash=%s:%*phN, real_hash=%s:%*phN" ,
262+ data_pos , level - 1 , params -> hash_alg -> name , hsize , want_hash ,
263+ params -> hash_alg -> name , hsize ,
264+ level == 0 ? dblock -> real_hash : real_hash );
235265error :
236266 for (; level > 0 ; level -- ) {
237267 kunmap_local (hblocks [level - 1 ].addr );
@@ -240,13 +270,73 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi,
240270 return false;
241271}
242272
243- static bool
244- verify_data_blocks (struct folio * data_folio , size_t len , size_t offset ,
245- unsigned long max_ra_pages )
273+ static void
274+ fsverity_init_verification_context (struct fsverity_verification_context * ctx ,
275+ struct inode * inode ,
276+ unsigned long max_ra_pages )
246277{
247- struct inode * inode = data_folio -> mapping -> host ;
248278 struct fsverity_info * vi = * fsverity_info_addr (inode );
249- const unsigned int block_size = vi -> tree_params .block_size ;
279+
280+ ctx -> inode = inode ;
281+ ctx -> vi = vi ;
282+ ctx -> max_ra_pages = max_ra_pages ;
283+ ctx -> num_pending = 0 ;
284+ if (vi -> tree_params .hash_alg -> algo_id == HASH_ALGO_SHA256 &&
285+ sha256_finup_2x_is_optimized ())
286+ ctx -> max_pending = 2 ;
287+ else
288+ ctx -> max_pending = 1 ;
289+ }
290+
291+ static void
292+ fsverity_clear_pending_blocks (struct fsverity_verification_context * ctx )
293+ {
294+ int i ;
295+
296+ for (i = ctx -> num_pending - 1 ; i >= 0 ; i -- ) {
297+ kunmap_local (ctx -> pending_blocks [i ].data );
298+ ctx -> pending_blocks [i ].data = NULL ;
299+ }
300+ ctx -> num_pending = 0 ;
301+ }
302+
303+ static bool
304+ fsverity_verify_pending_blocks (struct fsverity_verification_context * ctx )
305+ {
306+ struct fsverity_info * vi = ctx -> vi ;
307+ const struct merkle_tree_params * params = & vi -> tree_params ;
308+ int i ;
309+
310+ if (ctx -> num_pending == 2 ) {
311+ /* num_pending == 2 implies that the algorithm is SHA-256 */
312+ sha256_finup_2x (params -> hashstate ? & params -> hashstate -> sha256 :
313+ NULL ,
314+ ctx -> pending_blocks [0 ].data ,
315+ ctx -> pending_blocks [1 ].data , params -> block_size ,
316+ ctx -> pending_blocks [0 ].real_hash ,
317+ ctx -> pending_blocks [1 ].real_hash );
318+ } else {
319+ for (i = 0 ; i < ctx -> num_pending ; i ++ )
320+ fsverity_hash_block (params , ctx -> pending_blocks [i ].data ,
321+ ctx -> pending_blocks [i ].real_hash );
322+ }
323+
324+ for (i = 0 ; i < ctx -> num_pending ; i ++ ) {
325+ if (!verify_data_block (ctx -> inode , vi , & ctx -> pending_blocks [i ],
326+ ctx -> max_ra_pages ))
327+ return false;
328+ }
329+ fsverity_clear_pending_blocks (ctx );
330+ return true;
331+ }
332+
333+ static bool fsverity_add_data_blocks (struct fsverity_verification_context * ctx ,
334+ struct folio * data_folio , size_t len ,
335+ size_t offset )
336+ {
337+ struct fsverity_info * vi = ctx -> vi ;
338+ const struct merkle_tree_params * params = & vi -> tree_params ;
339+ const unsigned int block_size = params -> block_size ;
250340 u64 pos = (u64 )data_folio -> index << PAGE_SHIFT ;
251341
252342 if (WARN_ON_ONCE (len <= 0 || !IS_ALIGNED (len | offset , block_size )))
@@ -255,14 +345,11 @@ verify_data_blocks(struct folio *data_folio, size_t len, size_t offset,
255345 folio_test_uptodate (data_folio )))
256346 return false;
257347 do {
258- void * data ;
259- bool valid ;
260-
261- data = kmap_local_folio (data_folio , offset );
262- valid = verify_data_block (inode , vi , data , pos + offset ,
263- max_ra_pages );
264- kunmap_local (data );
265- if (!valid )
348+ ctx -> pending_blocks [ctx -> num_pending ].data =
349+ kmap_local_folio (data_folio , offset );
350+ ctx -> pending_blocks [ctx -> num_pending ].pos = pos + offset ;
351+ if (++ ctx -> num_pending == ctx -> max_pending &&
352+ !fsverity_verify_pending_blocks (ctx ))
266353 return false;
267354 offset += block_size ;
268355 len -= block_size ;
@@ -284,7 +371,15 @@ verify_data_blocks(struct folio *data_folio, size_t len, size_t offset,
284371 */
285372bool fsverity_verify_blocks (struct folio * folio , size_t len , size_t offset )
286373{
287- return verify_data_blocks (folio , len , offset , 0 );
374+ struct fsverity_verification_context ctx ;
375+
376+ fsverity_init_verification_context (& ctx , folio -> mapping -> host , 0 );
377+
378+ if (fsverity_add_data_blocks (& ctx , folio , len , offset ) &&
379+ fsverity_verify_pending_blocks (& ctx ))
380+ return true;
381+ fsverity_clear_pending_blocks (& ctx );
382+ return false;
288383}
289384EXPORT_SYMBOL_GPL (fsverity_verify_blocks );
290385
@@ -305,6 +400,8 @@ EXPORT_SYMBOL_GPL(fsverity_verify_blocks);
305400 */
306401void fsverity_verify_bio (struct bio * bio )
307402{
403+ struct inode * inode = bio_first_folio_all (bio )-> mapping -> host ;
404+ struct fsverity_verification_context ctx ;
308405 struct folio_iter fi ;
309406 unsigned long max_ra_pages = 0 ;
310407
@@ -321,13 +418,21 @@ void fsverity_verify_bio(struct bio *bio)
321418 max_ra_pages = bio -> bi_iter .bi_size >> (PAGE_SHIFT + 2 );
322419 }
323420
421+ fsverity_init_verification_context (& ctx , inode , max_ra_pages );
422+
324423 bio_for_each_folio_all (fi , bio ) {
325- if (!verify_data_blocks (fi .folio , fi .length , fi .offset ,
326- max_ra_pages )) {
327- bio -> bi_status = BLK_STS_IOERR ;
328- break ;
329- }
424+ if (!fsverity_add_data_blocks (& ctx , fi .folio , fi .length ,
425+ fi .offset ))
426+ goto ioerr ;
330427 }
428+
429+ if (!fsverity_verify_pending_blocks (& ctx ))
430+ goto ioerr ;
431+ return ;
432+
433+ ioerr :
434+ fsverity_clear_pending_blocks (& ctx );
435+ bio -> bi_status = BLK_STS_IOERR ;
331436}
332437EXPORT_SYMBOL_GPL (fsverity_verify_bio );
333438#endif /* CONFIG_BLOCK */
0 commit comments