Lines Matching +full:page +full:- +full:level
1 // SPDX-License-Identifier: GPL-2.0
3 * fs/verity/verify.c: data verification functions, i.e. hooks for ->readpages()
17 * hash_at_level() - compute the location of the block's hash at the given level
21 * @level: (in) the level of hash we want (0 is leaf level)
26 pgoff_t dindex, unsigned int level, pgoff_t *hindex, in hash_at_level() argument
31 /* Offset of the hash within the level's region, in hashes */ in hash_at_level()
32 position = dindex >> (level * params->log_arity); in hash_at_level()
35 *hindex = params->level_start[level] + (position >> params->log_arity); in hash_at_level()
38 *hoffset = (position & ((1 << params->log_arity) - 1)) << in hash_at_level()
39 (params->log_blocksize - params->log_arity); in hash_at_level()
42 /* Extract a hash from a hash page */
43 static void extract_hash(struct page *hpage, unsigned int hoffset, in extract_hash()
54 pgoff_t index, int level) in cmp_hashes() argument
56 const unsigned int hsize = vi->tree_params.digest_size; in cmp_hashes()
61 fsverity_err(vi->inode, in cmp_hashes()
62 "FILE CORRUPTED! index=%lu, level=%d, want_hash=%s:%*phN, real_hash=%s:%*phN", in cmp_hashes()
63 index, level, in cmp_hashes()
64 vi->tree_params.hash_alg->name, hsize, want_hash, in cmp_hashes()
65 vi->tree_params.hash_alg->name, hsize, real_hash); in cmp_hashes()
66 return -EBADMSG; in cmp_hashes()
70 * Verify a single data page against the file's Merkle tree.
74 * only ascend the tree until an already-verified page is seen, as indicated by
75 * the PageChecked bit being set; then verify the path to that page.
81 * Note that multiple processes may race to verify a hash page and mark it
84 * Return: true if the page is valid, else false.
87 struct ahash_request *req, struct page *data_page, in verify_page()
90 const struct merkle_tree_params *params = &vi->tree_params; in verify_page()
91 const unsigned int hsize = params->digest_size; in verify_page()
92 const pgoff_t index = data_page->index; in verify_page()
93 int level; in verify_page() local
97 struct page *hpages[FS_VERITY_MAX_LEVELS]; in verify_page()
104 pr_debug_ratelimited("Verifying data page %lu...\n", index); in verify_page()
107 if (index >= DIV_ROUND_UP(vi->verified_data_size, PAGE_SIZE)) { in verify_page()
109 vi->verified_data_size >> PAGE_SHIFT); in verify_page()
114 * Starting at the leaf level, ascend the tree saving hash pages along in verify_page()
115 * the way until we find a verified hash page, indicated by PageChecked; in verify_page()
118 for (level = 0; level < params->num_levels; level++) { in verify_page()
121 struct page *hpage; in verify_page()
123 hash_at_level(params, index, level, &hindex, &hoffset); in verify_page()
125 pr_debug_ratelimited("Level %d: hindex=%lu, hoffset=%u\n", in verify_page()
126 level, hindex, hoffset); in verify_page()
128 hpage = inode->i_sb->s_vop->read_merkle_tree_page(inode, hindex, in verify_page()
129 level == 0 ? level0_ra_pages : 0); in verify_page()
133 "Error %d reading Merkle tree page %lu", in verify_page()
142 pr_debug_ratelimited("Hash page already checked, want %s:%*phN\n", in verify_page()
143 params->hash_alg->name, in verify_page()
147 pr_debug_ratelimited("Hash page not yet checked\n"); in verify_page()
148 hpages[level] = hpage; in verify_page()
149 hoffsets[level] = hoffset; in verify_page()
152 want_hash = vi->root_hash; in verify_page()
154 params->hash_alg->name, hsize, want_hash); in verify_page()
157 for (; level > 0; level--) { in verify_page()
158 struct page *hpage = hpages[level - 1]; in verify_page()
159 unsigned int hoffset = hoffsets[level - 1]; in verify_page()
164 err = cmp_hashes(vi, want_hash, real_hash, index, level - 1); in verify_page()
171 pr_debug("Verified hash page at level %d, now want %s:%*phN\n", in verify_page()
172 level - 1, params->hash_alg->name, hsize, want_hash); in verify_page()
175 /* Finally, verify the data page */ in verify_page()
179 err = cmp_hashes(vi, want_hash, real_hash, index, -1); in verify_page()
181 for (; level > 0; level--) in verify_page()
182 put_page(hpages[level - 1]); in verify_page()
188 * fsverity_verify_page() - verify a data page
189 * @page: the page to verity
191 * Verify a page that has just been read from a verity file. The page must be a
192 * pagecache page that is still locked and not yet uptodate.
194 * Return: true if the page is valid, else false.
196 bool fsverity_verify_page(struct page *page) in fsverity_verify_page() argument
198 struct inode *inode = page->mapping->host; in fsverity_verify_page()
199 const struct fsverity_info *vi = inode->i_verity_info; in fsverity_verify_page()
203 /* This allocation never fails, since it's mempool-backed. */ in fsverity_verify_page()
204 req = fsverity_alloc_hash_request(vi->tree_params.hash_alg, GFP_NOFS); in fsverity_verify_page()
206 valid = verify_page(inode, vi, req, page, 0); in fsverity_verify_page()
208 fsverity_free_hash_request(vi->tree_params.hash_alg, req); in fsverity_verify_page()
216 * fsverity_verify_bio() - verify a 'read' bio that has just completed
224 * This is a helper function for use by the ->readpages() method of filesystems
225 * that issue bios to read data directly into the page cache. Filesystems that
226 * populate the page cache without issuing bios (e.g. non block-based
227 * filesystems) must instead call fsverity_verify_page() directly on each page.
232 struct inode *inode = bio_first_page_all(bio)->mapping->host; in fsverity_verify_bio()
233 const struct fsverity_info *vi = inode->i_verity_info; in fsverity_verify_bio()
234 const struct merkle_tree_params *params = &vi->tree_params; in fsverity_verify_bio()
240 /* This allocation never fails, since it's mempool-backed. */ in fsverity_verify_bio()
241 req = fsverity_alloc_hash_request(params->hash_alg, GFP_NOFS); in fsverity_verify_bio()
243 if (bio->bi_opf & REQ_RAHEAD) { in fsverity_verify_bio()
246 * of the first (largest) level of the Merkle tree. Namely, in fsverity_verify_bio()
247 * when a Merkle tree page is read, we also try to piggy-back on in fsverity_verify_bio()
248 * some additional pages -- up to 1/4 the number of data pages. in fsverity_verify_bio()
259 struct page *page = bv->bv_page; in fsverity_verify_bio() local
260 unsigned long level0_index = page->index >> params->log_arity; in fsverity_verify_bio()
262 min(max_ra_pages, params->level0_blocks - level0_index); in fsverity_verify_bio()
264 if (!PageError(page) && in fsverity_verify_bio()
265 !verify_page(inode, vi, req, page, level0_ra_pages)) in fsverity_verify_bio()
266 SetPageError(page); in fsverity_verify_bio()
269 fsverity_free_hash_request(params->hash_alg, req); in fsverity_verify_bio()
276 * fsverity_get_verified_data_size() - get verified data size of a verity file
284 return fsverity_get_info(inode)->verified_data_size; in fsverity_get_verified_data_size()
286 return inode->i_size; in fsverity_get_verified_data_size()
292 * fsverity_enqueue_verify_work() - enqueue work on the fs-verity workqueue
306 * Use a high-priority workqueue to prioritize verification work, which in fsverity_init_workqueue()
317 return -ENOMEM; in fsverity_init_workqueue()