xref: /openbmc/linux/fs/verity/enable.c (revision 56124d6c)
13fda4c61SEric Biggers // SPDX-License-Identifier: GPL-2.0
23fda4c61SEric Biggers /*
37bf765ddSEric Biggers  * Ioctl to enable verity on a file
43fda4c61SEric Biggers  *
53fda4c61SEric Biggers  * Copyright 2019 Google LLC
63fda4c61SEric Biggers  */
73fda4c61SEric Biggers 
83fda4c61SEric Biggers #include "fsverity_private.h"
93fda4c61SEric Biggers 
103fda4c61SEric Biggers #include <linux/mount.h>
113fda4c61SEric Biggers #include <linux/pagemap.h>
123fda4c61SEric Biggers #include <linux/sched/signal.h>
133fda4c61SEric Biggers #include <linux/uaccess.h>
143fda4c61SEric Biggers 
15*56124d6cSEric Biggers struct block_buffer {
16*56124d6cSEric Biggers 	u32 filled;
17*56124d6cSEric Biggers 	u8 *data;
18*56124d6cSEric Biggers };
19c22415d3SEric Biggers 
20*56124d6cSEric Biggers /* Hash a block, writing the result to the next level's pending block buffer. */
21*56124d6cSEric Biggers static int hash_one_block(struct inode *inode,
223fda4c61SEric Biggers 			  const struct merkle_tree_params *params,
23*56124d6cSEric Biggers 			  struct ahash_request *req, struct block_buffer *cur)
243fda4c61SEric Biggers {
25*56124d6cSEric Biggers 	struct block_buffer *next = cur + 1;
263fda4c61SEric Biggers 	int err;
273fda4c61SEric Biggers 
28*56124d6cSEric Biggers 	/* Zero-pad the block if it's shorter than the block size. */
29*56124d6cSEric Biggers 	memset(&cur->data[cur->filled], 0, params->block_size - cur->filled);
303fda4c61SEric Biggers 
31*56124d6cSEric Biggers 	err = fsverity_hash_block(params, inode, req, virt_to_page(cur->data),
32*56124d6cSEric Biggers 				  offset_in_page(cur->data),
33*56124d6cSEric Biggers 				  &next->data[next->filled]);
343fda4c61SEric Biggers 	if (err)
353fda4c61SEric Biggers 		return err;
36*56124d6cSEric Biggers 	next->filled += params->digest_size;
37*56124d6cSEric Biggers 	cur->filled = 0;
383fda4c61SEric Biggers 	return 0;
39*56124d6cSEric Biggers }
403fda4c61SEric Biggers 
41*56124d6cSEric Biggers static int write_merkle_tree_block(struct inode *inode, const u8 *buf,
42*56124d6cSEric Biggers 				   unsigned long index,
43*56124d6cSEric Biggers 				   const struct merkle_tree_params *params)
44*56124d6cSEric Biggers {
45*56124d6cSEric Biggers 	u64 pos = (u64)index << params->log_blocksize;
46*56124d6cSEric Biggers 	int err;
47*56124d6cSEric Biggers 
48*56124d6cSEric Biggers 	err = inode->i_sb->s_vop->write_merkle_tree_block(inode, buf, pos,
4972ea15f0SEric Biggers 							  params->block_size);
50*56124d6cSEric Biggers 	if (err)
51*56124d6cSEric Biggers 		fsverity_err(inode, "Error %d writing Merkle tree block %lu",
52*56124d6cSEric Biggers 			     err, index);
533fda4c61SEric Biggers 	return err;
543fda4c61SEric Biggers }
553fda4c61SEric Biggers 
563fda4c61SEric Biggers /*
57c22415d3SEric Biggers  * Build the Merkle tree for the given file using the given parameters, and
583fda4c61SEric Biggers  * return the root hash in @root_hash.
593fda4c61SEric Biggers  *
603fda4c61SEric Biggers  * The tree is written to a filesystem-specific location as determined by the
613fda4c61SEric Biggers  * ->write_merkle_tree_block() method.  However, the blocks that comprise the
623fda4c61SEric Biggers  * tree are the same for all filesystems.
633fda4c61SEric Biggers  */
64c22415d3SEric Biggers static int build_merkle_tree(struct file *filp,
653fda4c61SEric Biggers 			     const struct merkle_tree_params *params,
663fda4c61SEric Biggers 			     u8 *root_hash)
673fda4c61SEric Biggers {
68c22415d3SEric Biggers 	struct inode *inode = file_inode(filp);
69*56124d6cSEric Biggers 	const u64 data_size = inode->i_size;
70*56124d6cSEric Biggers 	const int num_levels = params->num_levels;
713fda4c61SEric Biggers 	struct ahash_request *req;
72*56124d6cSEric Biggers 	struct block_buffer _buffers[1 + FS_VERITY_MAX_LEVELS + 1] = {};
73*56124d6cSEric Biggers 	struct block_buffer *buffers = &_buffers[1];
74*56124d6cSEric Biggers 	unsigned long level_offset[FS_VERITY_MAX_LEVELS];
75*56124d6cSEric Biggers 	int level;
76*56124d6cSEric Biggers 	u64 offset;
77*56124d6cSEric Biggers 	int err;
783fda4c61SEric Biggers 
79*56124d6cSEric Biggers 	if (data_size == 0) {
803fda4c61SEric Biggers 		/* Empty file is a special case; root hash is all 0's */
813fda4c61SEric Biggers 		memset(root_hash, 0, params->digest_size);
823fda4c61SEric Biggers 		return 0;
833fda4c61SEric Biggers 	}
843fda4c61SEric Biggers 
85439bea10SEric Biggers 	/* This allocation never fails, since it's mempool-backed. */
86439bea10SEric Biggers 	req = fsverity_alloc_hash_request(params->hash_alg, GFP_KERNEL);
87439bea10SEric Biggers 
883fda4c61SEric Biggers 	/*
89*56124d6cSEric Biggers 	 * Allocate the block buffers.  Buffer "-1" is for data blocks.
90*56124d6cSEric Biggers 	 * Buffers 0 <= level < num_levels are for the actual tree levels.
91*56124d6cSEric Biggers 	 * Buffer 'num_levels' is for the root hash.
923fda4c61SEric Biggers 	 */
93*56124d6cSEric Biggers 	for (level = -1; level < num_levels; level++) {
94*56124d6cSEric Biggers 		buffers[level].data = kzalloc(params->block_size, GFP_KERNEL);
95*56124d6cSEric Biggers 		if (!buffers[level].data) {
96*56124d6cSEric Biggers 			err = -ENOMEM;
97*56124d6cSEric Biggers 			goto out;
98*56124d6cSEric Biggers 		}
99*56124d6cSEric Biggers 	}
100*56124d6cSEric Biggers 	buffers[num_levels].data = root_hash;
101*56124d6cSEric Biggers 
102*56124d6cSEric Biggers 	BUILD_BUG_ON(sizeof(level_offset) != sizeof(params->level_start));
103*56124d6cSEric Biggers 	memcpy(level_offset, params->level_start, sizeof(level_offset));
104*56124d6cSEric Biggers 
105*56124d6cSEric Biggers 	/* Hash each data block, also hashing the tree blocks as they fill up */
106*56124d6cSEric Biggers 	for (offset = 0; offset < data_size; offset += params->block_size) {
107*56124d6cSEric Biggers 		ssize_t bytes_read;
108*56124d6cSEric Biggers 		loff_t pos = offset;
109*56124d6cSEric Biggers 
110*56124d6cSEric Biggers 		buffers[-1].filled = min_t(u64, params->block_size,
111*56124d6cSEric Biggers 					   data_size - offset);
112*56124d6cSEric Biggers 		bytes_read = __kernel_read(filp, buffers[-1].data,
113*56124d6cSEric Biggers 					   buffers[-1].filled, &pos);
114*56124d6cSEric Biggers 		if (bytes_read < 0) {
115*56124d6cSEric Biggers 			err = bytes_read;
116*56124d6cSEric Biggers 			fsverity_err(inode, "Error %d reading file data", err);
117*56124d6cSEric Biggers 			goto out;
118*56124d6cSEric Biggers 		}
119*56124d6cSEric Biggers 		if (bytes_read != buffers[-1].filled) {
120*56124d6cSEric Biggers 			err = -EINVAL;
121*56124d6cSEric Biggers 			fsverity_err(inode, "Short read of file data");
122*56124d6cSEric Biggers 			goto out;
123*56124d6cSEric Biggers 		}
124*56124d6cSEric Biggers 		err = hash_one_block(inode, params, req, &buffers[-1]);
1253fda4c61SEric Biggers 		if (err)
1263fda4c61SEric Biggers 			goto out;
127*56124d6cSEric Biggers 		for (level = 0; level < num_levels; level++) {
128*56124d6cSEric Biggers 			if (buffers[level].filled + params->digest_size <=
129*56124d6cSEric Biggers 			    params->block_size) {
130*56124d6cSEric Biggers 				/* Next block at @level isn't full yet */
131*56124d6cSEric Biggers 				break;
1323fda4c61SEric Biggers 			}
133*56124d6cSEric Biggers 			/* Next block at @level is full */
134*56124d6cSEric Biggers 
135*56124d6cSEric Biggers 			err = hash_one_block(inode, params, req,
136*56124d6cSEric Biggers 					     &buffers[level]);
137*56124d6cSEric Biggers 			if (err)
138*56124d6cSEric Biggers 				goto out;
139*56124d6cSEric Biggers 			err = write_merkle_tree_block(inode,
140*56124d6cSEric Biggers 						      buffers[level].data,
141*56124d6cSEric Biggers 						      level_offset[level],
142*56124d6cSEric Biggers 						      params);
143*56124d6cSEric Biggers 			if (err)
144*56124d6cSEric Biggers 				goto out;
145*56124d6cSEric Biggers 			level_offset[level]++;
146*56124d6cSEric Biggers 		}
147*56124d6cSEric Biggers 		if (fatal_signal_pending(current)) {
148*56124d6cSEric Biggers 			err = -EINTR;
149*56124d6cSEric Biggers 			goto out;
150*56124d6cSEric Biggers 		}
151*56124d6cSEric Biggers 		cond_resched();
152*56124d6cSEric Biggers 	}
153*56124d6cSEric Biggers 	/* Finish all nonempty pending tree blocks. */
154*56124d6cSEric Biggers 	for (level = 0; level < num_levels; level++) {
155*56124d6cSEric Biggers 		if (buffers[level].filled != 0) {
156*56124d6cSEric Biggers 			err = hash_one_block(inode, params, req,
157*56124d6cSEric Biggers 					     &buffers[level]);
158*56124d6cSEric Biggers 			if (err)
159*56124d6cSEric Biggers 				goto out;
160*56124d6cSEric Biggers 			err = write_merkle_tree_block(inode,
161*56124d6cSEric Biggers 						      buffers[level].data,
162*56124d6cSEric Biggers 						      level_offset[level],
163*56124d6cSEric Biggers 						      params);
164*56124d6cSEric Biggers 			if (err)
165*56124d6cSEric Biggers 				goto out;
166*56124d6cSEric Biggers 		}
167*56124d6cSEric Biggers 	}
168*56124d6cSEric Biggers 	/* The root hash was filled by the last call to hash_one_block(). */
169*56124d6cSEric Biggers 	if (WARN_ON(buffers[num_levels].filled != params->digest_size)) {
170*56124d6cSEric Biggers 		err = -EINVAL;
171*56124d6cSEric Biggers 		goto out;
172*56124d6cSEric Biggers 	}
1733fda4c61SEric Biggers 	err = 0;
1743fda4c61SEric Biggers out:
175*56124d6cSEric Biggers 	for (level = -1; level < num_levels; level++)
176*56124d6cSEric Biggers 		kfree(buffers[level].data);
177439bea10SEric Biggers 	fsverity_free_hash_request(params->hash_alg, req);
1783fda4c61SEric Biggers 	return err;
1793fda4c61SEric Biggers }
1803fda4c61SEric Biggers 
1813fda4c61SEric Biggers static int enable_verity(struct file *filp,
1823fda4c61SEric Biggers 			 const struct fsverity_enable_arg *arg)
1833fda4c61SEric Biggers {
1843fda4c61SEric Biggers 	struct inode *inode = file_inode(filp);
1853fda4c61SEric Biggers 	const struct fsverity_operations *vops = inode->i_sb->s_vop;
1863fda4c61SEric Biggers 	struct merkle_tree_params params = { };
1873fda4c61SEric Biggers 	struct fsverity_descriptor *desc;
188e6af1bb0SZhang Jianhua 	size_t desc_size = struct_size(desc, signature, arg->sig_size);
1893fda4c61SEric Biggers 	struct fsverity_info *vi;
1903fda4c61SEric Biggers 	int err;
1913fda4c61SEric Biggers 
1923fda4c61SEric Biggers 	/* Start initializing the fsverity_descriptor */
1933fda4c61SEric Biggers 	desc = kzalloc(desc_size, GFP_KERNEL);
1943fda4c61SEric Biggers 	if (!desc)
1953fda4c61SEric Biggers 		return -ENOMEM;
1963fda4c61SEric Biggers 	desc->version = 1;
1973fda4c61SEric Biggers 	desc->hash_algorithm = arg->hash_algorithm;
1983fda4c61SEric Biggers 	desc->log_blocksize = ilog2(arg->block_size);
1993fda4c61SEric Biggers 
2003fda4c61SEric Biggers 	/* Get the salt if the user provided one */
2013fda4c61SEric Biggers 	if (arg->salt_size &&
202da3a3da4SEric Biggers 	    copy_from_user(desc->salt, u64_to_user_ptr(arg->salt_ptr),
2033fda4c61SEric Biggers 			   arg->salt_size)) {
2043fda4c61SEric Biggers 		err = -EFAULT;
2053fda4c61SEric Biggers 		goto out;
2063fda4c61SEric Biggers 	}
2073fda4c61SEric Biggers 	desc->salt_size = arg->salt_size;
2083fda4c61SEric Biggers 
209432434c9SEric Biggers 	/* Get the signature if the user provided one */
210432434c9SEric Biggers 	if (arg->sig_size &&
211da3a3da4SEric Biggers 	    copy_from_user(desc->signature, u64_to_user_ptr(arg->sig_ptr),
212432434c9SEric Biggers 			   arg->sig_size)) {
213432434c9SEric Biggers 		err = -EFAULT;
214432434c9SEric Biggers 		goto out;
215432434c9SEric Biggers 	}
216432434c9SEric Biggers 	desc->sig_size = cpu_to_le32(arg->sig_size);
217432434c9SEric Biggers 
2183fda4c61SEric Biggers 	desc->data_size = cpu_to_le64(inode->i_size);
2193fda4c61SEric Biggers 
2203fda4c61SEric Biggers 	/* Prepare the Merkle tree parameters */
2213fda4c61SEric Biggers 	err = fsverity_init_merkle_tree_params(&params, inode,
2223fda4c61SEric Biggers 					       arg->hash_algorithm,
2233fda4c61SEric Biggers 					       desc->log_blocksize,
2243fda4c61SEric Biggers 					       desc->salt, desc->salt_size);
2253fda4c61SEric Biggers 	if (err)
2263fda4c61SEric Biggers 		goto out;
2273fda4c61SEric Biggers 
2283fda4c61SEric Biggers 	/*
2293fda4c61SEric Biggers 	 * Start enabling verity on this file, serialized by the inode lock.
2303fda4c61SEric Biggers 	 * Fail if verity is already enabled or is already being enabled.
2313fda4c61SEric Biggers 	 */
2323fda4c61SEric Biggers 	inode_lock(inode);
2333fda4c61SEric Biggers 	if (IS_VERITY(inode))
2343fda4c61SEric Biggers 		err = -EEXIST;
2353fda4c61SEric Biggers 	else
2363fda4c61SEric Biggers 		err = vops->begin_enable_verity(filp);
2373fda4c61SEric Biggers 	inode_unlock(inode);
2383fda4c61SEric Biggers 	if (err)
2393fda4c61SEric Biggers 		goto out;
2403fda4c61SEric Biggers 
2413fda4c61SEric Biggers 	/*
2423fda4c61SEric Biggers 	 * Build the Merkle tree.  Don't hold the inode lock during this, since
2433fda4c61SEric Biggers 	 * on huge files this may take a very long time and we don't want to
2443fda4c61SEric Biggers 	 * force unrelated syscalls like chown() to block forever.  We don't
2453fda4c61SEric Biggers 	 * need the inode lock here because deny_write_access() already prevents
2463fda4c61SEric Biggers 	 * the file from being written to or truncated, and we still serialize
2473fda4c61SEric Biggers 	 * ->begin_enable_verity() and ->end_enable_verity() using the inode
2483fda4c61SEric Biggers 	 * lock and only allow one process to be here at a time on a given file.
2493fda4c61SEric Biggers 	 */
2503fda4c61SEric Biggers 	BUILD_BUG_ON(sizeof(desc->root_hash) < FS_VERITY_MAX_DIGEST_SIZE);
251c22415d3SEric Biggers 	err = build_merkle_tree(filp, &params, desc->root_hash);
2523fda4c61SEric Biggers 	if (err) {
2533fda4c61SEric Biggers 		fsverity_err(inode, "Error %d building Merkle tree", err);
2543fda4c61SEric Biggers 		goto rollback;
2553fda4c61SEric Biggers 	}
2563fda4c61SEric Biggers 
2573fda4c61SEric Biggers 	/*
2583fda4c61SEric Biggers 	 * Create the fsverity_info.  Don't bother trying to save work by
2593fda4c61SEric Biggers 	 * reusing the merkle_tree_params from above.  Instead, just create the
2603fda4c61SEric Biggers 	 * fsverity_info from the fsverity_descriptor as if it were just loaded
2613fda4c61SEric Biggers 	 * from disk.  This is simpler, and it serves as an extra check that the
2623fda4c61SEric Biggers 	 * metadata we're writing is valid before actually enabling verity.
2633fda4c61SEric Biggers 	 */
264b0487edeSZhang Jianhua 	vi = fsverity_create_info(inode, desc);
2653fda4c61SEric Biggers 	if (IS_ERR(vi)) {
2663fda4c61SEric Biggers 		err = PTR_ERR(vi);
2673fda4c61SEric Biggers 		goto rollback;
2683fda4c61SEric Biggers 	}
2693fda4c61SEric Biggers 
2703fda4c61SEric Biggers 	/*
2713fda4c61SEric Biggers 	 * Tell the filesystem to finish enabling verity on the file.
2723fda4c61SEric Biggers 	 * Serialized with ->begin_enable_verity() by the inode lock.
2733fda4c61SEric Biggers 	 */
2743fda4c61SEric Biggers 	inode_lock(inode);
2753fda4c61SEric Biggers 	err = vops->end_enable_verity(filp, desc, desc_size, params.tree_size);
2763fda4c61SEric Biggers 	inode_unlock(inode);
2773fda4c61SEric Biggers 	if (err) {
2783fda4c61SEric Biggers 		fsverity_err(inode, "%ps() failed with err %d",
2793fda4c61SEric Biggers 			     vops->end_enable_verity, err);
2803fda4c61SEric Biggers 		fsverity_free_info(vi);
2813fda4c61SEric Biggers 	} else if (WARN_ON(!IS_VERITY(inode))) {
2823fda4c61SEric Biggers 		err = -EINVAL;
2833fda4c61SEric Biggers 		fsverity_free_info(vi);
2843fda4c61SEric Biggers 	} else {
2853fda4c61SEric Biggers 		/* Successfully enabled verity */
2863fda4c61SEric Biggers 
2873fda4c61SEric Biggers 		/*
2883fda4c61SEric Biggers 		 * Readers can start using ->i_verity_info immediately, so it
2893fda4c61SEric Biggers 		 * can't be rolled back once set.  So don't set it until just
2903fda4c61SEric Biggers 		 * after the filesystem has successfully enabled verity.
2913fda4c61SEric Biggers 		 */
2923fda4c61SEric Biggers 		fsverity_set_info(inode, vi);
2933fda4c61SEric Biggers 	}
2943fda4c61SEric Biggers out:
2953fda4c61SEric Biggers 	kfree(params.hashstate);
2963fda4c61SEric Biggers 	kfree(desc);
2973fda4c61SEric Biggers 	return err;
2983fda4c61SEric Biggers 
2993fda4c61SEric Biggers rollback:
3003fda4c61SEric Biggers 	inode_lock(inode);
3013fda4c61SEric Biggers 	(void)vops->end_enable_verity(filp, NULL, 0, params.tree_size);
3023fda4c61SEric Biggers 	inode_unlock(inode);
3033fda4c61SEric Biggers 	goto out;
3043fda4c61SEric Biggers }
3053fda4c61SEric Biggers 
3063fda4c61SEric Biggers /**
3073fda4c61SEric Biggers  * fsverity_ioctl_enable() - enable verity on a file
3086377a38bSEric Biggers  * @filp: file to enable verity on
3096377a38bSEric Biggers  * @uarg: user pointer to fsverity_enable_arg
3103fda4c61SEric Biggers  *
3113fda4c61SEric Biggers  * Enable fs-verity on a file.  See the "FS_IOC_ENABLE_VERITY" section of
3123fda4c61SEric Biggers  * Documentation/filesystems/fsverity.rst for the documentation.
3133fda4c61SEric Biggers  *
3143fda4c61SEric Biggers  * Return: 0 on success, -errno on failure
3153fda4c61SEric Biggers  */
3163fda4c61SEric Biggers int fsverity_ioctl_enable(struct file *filp, const void __user *uarg)
3173fda4c61SEric Biggers {
3183fda4c61SEric Biggers 	struct inode *inode = file_inode(filp);
3193fda4c61SEric Biggers 	struct fsverity_enable_arg arg;
3203fda4c61SEric Biggers 	int err;
3213fda4c61SEric Biggers 
3223fda4c61SEric Biggers 	if (copy_from_user(&arg, uarg, sizeof(arg)))
3233fda4c61SEric Biggers 		return -EFAULT;
3243fda4c61SEric Biggers 
3253fda4c61SEric Biggers 	if (arg.version != 1)
3263fda4c61SEric Biggers 		return -EINVAL;
3273fda4c61SEric Biggers 
3283fda4c61SEric Biggers 	if (arg.__reserved1 ||
3293fda4c61SEric Biggers 	    memchr_inv(arg.__reserved2, 0, sizeof(arg.__reserved2)))
3303fda4c61SEric Biggers 		return -EINVAL;
3313fda4c61SEric Biggers 
332*56124d6cSEric Biggers 	if (!is_power_of_2(arg.block_size))
3333fda4c61SEric Biggers 		return -EINVAL;
3343fda4c61SEric Biggers 
335c593642cSPankaj Bharadiya 	if (arg.salt_size > sizeof_field(struct fsverity_descriptor, salt))
3363fda4c61SEric Biggers 		return -EMSGSIZE;
3373fda4c61SEric Biggers 
338432434c9SEric Biggers 	if (arg.sig_size > FS_VERITY_MAX_SIGNATURE_SIZE)
339432434c9SEric Biggers 		return -EMSGSIZE;
3403fda4c61SEric Biggers 
3413fda4c61SEric Biggers 	/*
3423fda4c61SEric Biggers 	 * Require a regular file with write access.  But the actual fd must
3433fda4c61SEric Biggers 	 * still be readonly so that we can lock out all writers.  This is
3443fda4c61SEric Biggers 	 * needed to guarantee that no writable fds exist to the file once it
3453fda4c61SEric Biggers 	 * has verity enabled, and to stabilize the data being hashed.
3463fda4c61SEric Biggers 	 */
3473fda4c61SEric Biggers 
34802f92b38SChristian Brauner 	err = file_permission(filp, MAY_WRITE);
3493fda4c61SEric Biggers 	if (err)
3503fda4c61SEric Biggers 		return err;
3513fda4c61SEric Biggers 
3523fda4c61SEric Biggers 	if (IS_APPEND(inode))
3533fda4c61SEric Biggers 		return -EPERM;
3543fda4c61SEric Biggers 
3553fda4c61SEric Biggers 	if (S_ISDIR(inode->i_mode))
3563fda4c61SEric Biggers 		return -EISDIR;
3573fda4c61SEric Biggers 
3583fda4c61SEric Biggers 	if (!S_ISREG(inode->i_mode))
3593fda4c61SEric Biggers 		return -EINVAL;
3603fda4c61SEric Biggers 
3613fda4c61SEric Biggers 	err = mnt_want_write_file(filp);
3623fda4c61SEric Biggers 	if (err) /* -EROFS */
3633fda4c61SEric Biggers 		return err;
3643fda4c61SEric Biggers 
3653fda4c61SEric Biggers 	err = deny_write_access(filp);
3663fda4c61SEric Biggers 	if (err) /* -ETXTBSY */
3673fda4c61SEric Biggers 		goto out_drop_write;
3683fda4c61SEric Biggers 
3693fda4c61SEric Biggers 	err = enable_verity(filp, &arg);
3703fda4c61SEric Biggers 	if (err)
3713fda4c61SEric Biggers 		goto out_allow_write_access;
3723fda4c61SEric Biggers 
3733fda4c61SEric Biggers 	/*
3743fda4c61SEric Biggers 	 * Some pages of the file may have been evicted from pagecache after
3753fda4c61SEric Biggers 	 * being used in the Merkle tree construction, then read into pagecache
3763fda4c61SEric Biggers 	 * again by another process reading from the file concurrently.  Since
377ed45e201SEric Biggers 	 * these pages didn't undergo verification against the file digest which
378ed45e201SEric Biggers 	 * fs-verity now claims to be enforcing, we have to wipe the pagecache
379ed45e201SEric Biggers 	 * to ensure that all future reads are verified.
3803fda4c61SEric Biggers 	 */
3813fda4c61SEric Biggers 	filemap_write_and_wait(inode->i_mapping);
3823fda4c61SEric Biggers 	invalidate_inode_pages2(inode->i_mapping);
3833fda4c61SEric Biggers 
3843fda4c61SEric Biggers 	/*
3853fda4c61SEric Biggers 	 * allow_write_access() is needed to pair with deny_write_access().
3863fda4c61SEric Biggers 	 * Regardless, the filesystem won't allow writing to verity files.
3873fda4c61SEric Biggers 	 */
3883fda4c61SEric Biggers out_allow_write_access:
3893fda4c61SEric Biggers 	allow_write_access(filp);
3903fda4c61SEric Biggers out_drop_write:
3913fda4c61SEric Biggers 	mnt_drop_write_file(filp);
3923fda4c61SEric Biggers 	return err;
3933fda4c61SEric Biggers }
3943fda4c61SEric Biggers EXPORT_SYMBOL_GPL(fsverity_ioctl_enable);
395