xref: /openbmc/linux/fs/verity/enable.c (revision 7bf765dd)
13fda4c61SEric Biggers // SPDX-License-Identifier: GPL-2.0
23fda4c61SEric Biggers /*
3*7bf765ddSEric 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 <crypto/hash.h>
11fd39073dSEric Biggers #include <linux/backing-dev.h>
123fda4c61SEric Biggers #include <linux/mount.h>
133fda4c61SEric Biggers #include <linux/pagemap.h>
143fda4c61SEric Biggers #include <linux/sched/signal.h>
153fda4c61SEric Biggers #include <linux/uaccess.h>
163fda4c61SEric Biggers 
17c22415d3SEric Biggers /*
18c22415d3SEric Biggers  * Read a file data page for Merkle tree construction.  Do aggressive readahead,
19c22415d3SEric Biggers  * since we're sequentially reading the entire file.
20c22415d3SEric Biggers  */
21c22415d3SEric Biggers static struct page *read_file_data_page(struct file *filp, pgoff_t index,
22c22415d3SEric Biggers 					struct file_ra_state *ra,
23c22415d3SEric Biggers 					unsigned long remaining_pages)
24c22415d3SEric Biggers {
25c22415d3SEric Biggers 	struct page *page;
26c22415d3SEric Biggers 
27c22415d3SEric Biggers 	page = find_get_page_flags(filp->f_mapping, index, FGP_ACCESSED);
28c22415d3SEric Biggers 	if (!page || !PageUptodate(page)) {
29c22415d3SEric Biggers 		if (page)
30c22415d3SEric Biggers 			put_page(page);
31c22415d3SEric Biggers 		else
32c22415d3SEric Biggers 			page_cache_sync_readahead(filp->f_mapping, ra, filp,
33c22415d3SEric Biggers 						  index, remaining_pages);
34c22415d3SEric Biggers 		page = read_mapping_page(filp->f_mapping, index, NULL);
35c22415d3SEric Biggers 		if (IS_ERR(page))
36c22415d3SEric Biggers 			return page;
37c22415d3SEric Biggers 	}
38c22415d3SEric Biggers 	if (PageReadahead(page))
39c22415d3SEric Biggers 		page_cache_async_readahead(filp->f_mapping, ra, filp, page,
40c22415d3SEric Biggers 					   index, remaining_pages);
41c22415d3SEric Biggers 	return page;
42c22415d3SEric Biggers }
43c22415d3SEric Biggers 
44c22415d3SEric Biggers static int build_merkle_tree_level(struct file *filp, unsigned int level,
453fda4c61SEric Biggers 				   u64 num_blocks_to_hash,
463fda4c61SEric Biggers 				   const struct merkle_tree_params *params,
473fda4c61SEric Biggers 				   u8 *pending_hashes,
483fda4c61SEric Biggers 				   struct ahash_request *req)
493fda4c61SEric Biggers {
50c22415d3SEric Biggers 	struct inode *inode = file_inode(filp);
513fda4c61SEric Biggers 	const struct fsverity_operations *vops = inode->i_sb->s_vop;
52c22415d3SEric Biggers 	struct file_ra_state ra = { 0 };
533fda4c61SEric Biggers 	unsigned int pending_size = 0;
543fda4c61SEric Biggers 	u64 dst_block_num;
553fda4c61SEric Biggers 	u64 i;
563fda4c61SEric Biggers 	int err;
573fda4c61SEric Biggers 
583fda4c61SEric Biggers 	if (WARN_ON(params->block_size != PAGE_SIZE)) /* checked earlier too */
593fda4c61SEric Biggers 		return -EINVAL;
603fda4c61SEric Biggers 
613fda4c61SEric Biggers 	if (level < params->num_levels) {
623fda4c61SEric Biggers 		dst_block_num = params->level_start[level];
633fda4c61SEric Biggers 	} else {
643fda4c61SEric Biggers 		if (WARN_ON(num_blocks_to_hash != 1))
653fda4c61SEric Biggers 			return -EINVAL;
663fda4c61SEric Biggers 		dst_block_num = 0; /* unused */
673fda4c61SEric Biggers 	}
683fda4c61SEric Biggers 
69c22415d3SEric Biggers 	file_ra_state_init(&ra, filp->f_mapping);
70c22415d3SEric Biggers 
713fda4c61SEric Biggers 	for (i = 0; i < num_blocks_to_hash; i++) {
723fda4c61SEric Biggers 		struct page *src_page;
733fda4c61SEric Biggers 
743fda4c61SEric Biggers 		if ((pgoff_t)i % 10000 == 0 || i + 1 == num_blocks_to_hash)
753fda4c61SEric Biggers 			pr_debug("Hashing block %llu of %llu for level %u\n",
763fda4c61SEric Biggers 				 i + 1, num_blocks_to_hash, level);
773fda4c61SEric Biggers 
783fda4c61SEric Biggers 		if (level == 0) {
793fda4c61SEric Biggers 			/* Leaf: hashing a data block */
80c22415d3SEric Biggers 			src_page = read_file_data_page(filp, i, &ra,
81c22415d3SEric Biggers 						       num_blocks_to_hash - i);
823fda4c61SEric Biggers 			if (IS_ERR(src_page)) {
833fda4c61SEric Biggers 				err = PTR_ERR(src_page);
843fda4c61SEric Biggers 				fsverity_err(inode,
853fda4c61SEric Biggers 					     "Error %d reading data page %llu",
863fda4c61SEric Biggers 					     err, i);
873fda4c61SEric Biggers 				return err;
883fda4c61SEric Biggers 			}
893fda4c61SEric Biggers 		} else {
90fd39073dSEric Biggers 			unsigned long num_ra_pages =
91fd39073dSEric Biggers 				min_t(unsigned long, num_blocks_to_hash - i,
92fd39073dSEric Biggers 				      inode->i_sb->s_bdi->io_pages);
93fd39073dSEric Biggers 
943fda4c61SEric Biggers 			/* Non-leaf: hashing hash block from level below */
953fda4c61SEric Biggers 			src_page = vops->read_merkle_tree_page(inode,
96fd39073dSEric Biggers 					params->level_start[level - 1] + i,
97fd39073dSEric Biggers 					num_ra_pages);
983fda4c61SEric Biggers 			if (IS_ERR(src_page)) {
993fda4c61SEric Biggers 				err = PTR_ERR(src_page);
1003fda4c61SEric Biggers 				fsverity_err(inode,
1013fda4c61SEric Biggers 					     "Error %d reading Merkle tree page %llu",
1023fda4c61SEric Biggers 					     err, params->level_start[level - 1] + i);
1033fda4c61SEric Biggers 				return err;
1043fda4c61SEric Biggers 			}
1053fda4c61SEric Biggers 		}
1063fda4c61SEric Biggers 
1073fda4c61SEric Biggers 		err = fsverity_hash_page(params, inode, req, src_page,
1083fda4c61SEric Biggers 					 &pending_hashes[pending_size]);
1093fda4c61SEric Biggers 		put_page(src_page);
1103fda4c61SEric Biggers 		if (err)
1113fda4c61SEric Biggers 			return err;
1123fda4c61SEric Biggers 		pending_size += params->digest_size;
1133fda4c61SEric Biggers 
1143fda4c61SEric Biggers 		if (level == params->num_levels) /* Root hash? */
1153fda4c61SEric Biggers 			return 0;
1163fda4c61SEric Biggers 
1173fda4c61SEric Biggers 		if (pending_size + params->digest_size > params->block_size ||
1183fda4c61SEric Biggers 		    i + 1 == num_blocks_to_hash) {
1193fda4c61SEric Biggers 			/* Flush the pending hash block */
1203fda4c61SEric Biggers 			memset(&pending_hashes[pending_size], 0,
1213fda4c61SEric Biggers 			       params->block_size - pending_size);
1223fda4c61SEric Biggers 			err = vops->write_merkle_tree_block(inode,
1233fda4c61SEric Biggers 					pending_hashes,
1243fda4c61SEric Biggers 					dst_block_num,
1253fda4c61SEric Biggers 					params->log_blocksize);
1263fda4c61SEric Biggers 			if (err) {
1273fda4c61SEric Biggers 				fsverity_err(inode,
1283fda4c61SEric Biggers 					     "Error %d writing Merkle tree block %llu",
1293fda4c61SEric Biggers 					     err, dst_block_num);
1303fda4c61SEric Biggers 				return err;
1313fda4c61SEric Biggers 			}
1323fda4c61SEric Biggers 			dst_block_num++;
1333fda4c61SEric Biggers 			pending_size = 0;
1343fda4c61SEric Biggers 		}
1353fda4c61SEric Biggers 
1363fda4c61SEric Biggers 		if (fatal_signal_pending(current))
1373fda4c61SEric Biggers 			return -EINTR;
1383fda4c61SEric Biggers 		cond_resched();
1393fda4c61SEric Biggers 	}
1403fda4c61SEric Biggers 	return 0;
1413fda4c61SEric Biggers }
1423fda4c61SEric Biggers 
1433fda4c61SEric Biggers /*
144c22415d3SEric Biggers  * Build the Merkle tree for the given file using the given parameters, and
1453fda4c61SEric Biggers  * return the root hash in @root_hash.
1463fda4c61SEric Biggers  *
1473fda4c61SEric Biggers  * The tree is written to a filesystem-specific location as determined by the
1483fda4c61SEric Biggers  * ->write_merkle_tree_block() method.  However, the blocks that comprise the
1493fda4c61SEric Biggers  * tree are the same for all filesystems.
1503fda4c61SEric Biggers  */
151c22415d3SEric Biggers static int build_merkle_tree(struct file *filp,
1523fda4c61SEric Biggers 			     const struct merkle_tree_params *params,
1533fda4c61SEric Biggers 			     u8 *root_hash)
1543fda4c61SEric Biggers {
155c22415d3SEric Biggers 	struct inode *inode = file_inode(filp);
1563fda4c61SEric Biggers 	u8 *pending_hashes;
1573fda4c61SEric Biggers 	struct ahash_request *req;
1583fda4c61SEric Biggers 	u64 blocks;
1593fda4c61SEric Biggers 	unsigned int level;
1603fda4c61SEric Biggers 	int err = -ENOMEM;
1613fda4c61SEric Biggers 
1623fda4c61SEric Biggers 	if (inode->i_size == 0) {
1633fda4c61SEric Biggers 		/* Empty file is a special case; root hash is all 0's */
1643fda4c61SEric Biggers 		memset(root_hash, 0, params->digest_size);
1653fda4c61SEric Biggers 		return 0;
1663fda4c61SEric Biggers 	}
1673fda4c61SEric Biggers 
168439bea10SEric Biggers 	/* This allocation never fails, since it's mempool-backed. */
169439bea10SEric Biggers 	req = fsverity_alloc_hash_request(params->hash_alg, GFP_KERNEL);
170439bea10SEric Biggers 
1713fda4c61SEric Biggers 	pending_hashes = kmalloc(params->block_size, GFP_KERNEL);
172439bea10SEric Biggers 	if (!pending_hashes)
1733fda4c61SEric Biggers 		goto out;
1743fda4c61SEric Biggers 
1753fda4c61SEric Biggers 	/*
1763fda4c61SEric Biggers 	 * Build each level of the Merkle tree, starting at the leaf level
1773fda4c61SEric Biggers 	 * (level 0) and ascending to the root node (level 'num_levels - 1').
1783fda4c61SEric Biggers 	 * Then at the end (level 'num_levels'), calculate the root hash.
1793fda4c61SEric Biggers 	 */
1803fda4c61SEric Biggers 	blocks = (inode->i_size + params->block_size - 1) >>
1813fda4c61SEric Biggers 		 params->log_blocksize;
1823fda4c61SEric Biggers 	for (level = 0; level <= params->num_levels; level++) {
183c22415d3SEric Biggers 		err = build_merkle_tree_level(filp, level, blocks, params,
1843fda4c61SEric Biggers 					      pending_hashes, req);
1853fda4c61SEric Biggers 		if (err)
1863fda4c61SEric Biggers 			goto out;
1873fda4c61SEric Biggers 		blocks = (blocks + params->hashes_per_block - 1) >>
1883fda4c61SEric Biggers 			 params->log_arity;
1893fda4c61SEric Biggers 	}
1903fda4c61SEric Biggers 	memcpy(root_hash, pending_hashes, params->digest_size);
1913fda4c61SEric Biggers 	err = 0;
1923fda4c61SEric Biggers out:
1933fda4c61SEric Biggers 	kfree(pending_hashes);
194439bea10SEric Biggers 	fsverity_free_hash_request(params->hash_alg, req);
1953fda4c61SEric Biggers 	return err;
1963fda4c61SEric Biggers }
1973fda4c61SEric Biggers 
1983fda4c61SEric Biggers static int enable_verity(struct file *filp,
1993fda4c61SEric Biggers 			 const struct fsverity_enable_arg *arg)
2003fda4c61SEric Biggers {
2013fda4c61SEric Biggers 	struct inode *inode = file_inode(filp);
2023fda4c61SEric Biggers 	const struct fsverity_operations *vops = inode->i_sb->s_vop;
2033fda4c61SEric Biggers 	struct merkle_tree_params params = { };
2043fda4c61SEric Biggers 	struct fsverity_descriptor *desc;
205432434c9SEric Biggers 	size_t desc_size = sizeof(*desc) + arg->sig_size;
2063fda4c61SEric Biggers 	struct fsverity_info *vi;
2073fda4c61SEric Biggers 	int err;
2083fda4c61SEric Biggers 
2093fda4c61SEric Biggers 	/* Start initializing the fsverity_descriptor */
2103fda4c61SEric Biggers 	desc = kzalloc(desc_size, GFP_KERNEL);
2113fda4c61SEric Biggers 	if (!desc)
2123fda4c61SEric Biggers 		return -ENOMEM;
2133fda4c61SEric Biggers 	desc->version = 1;
2143fda4c61SEric Biggers 	desc->hash_algorithm = arg->hash_algorithm;
2153fda4c61SEric Biggers 	desc->log_blocksize = ilog2(arg->block_size);
2163fda4c61SEric Biggers 
2173fda4c61SEric Biggers 	/* Get the salt if the user provided one */
2183fda4c61SEric Biggers 	if (arg->salt_size &&
219da3a3da4SEric Biggers 	    copy_from_user(desc->salt, u64_to_user_ptr(arg->salt_ptr),
2203fda4c61SEric Biggers 			   arg->salt_size)) {
2213fda4c61SEric Biggers 		err = -EFAULT;
2223fda4c61SEric Biggers 		goto out;
2233fda4c61SEric Biggers 	}
2243fda4c61SEric Biggers 	desc->salt_size = arg->salt_size;
2253fda4c61SEric Biggers 
226432434c9SEric Biggers 	/* Get the signature if the user provided one */
227432434c9SEric Biggers 	if (arg->sig_size &&
228da3a3da4SEric Biggers 	    copy_from_user(desc->signature, u64_to_user_ptr(arg->sig_ptr),
229432434c9SEric Biggers 			   arg->sig_size)) {
230432434c9SEric Biggers 		err = -EFAULT;
231432434c9SEric Biggers 		goto out;
232432434c9SEric Biggers 	}
233432434c9SEric Biggers 	desc->sig_size = cpu_to_le32(arg->sig_size);
234432434c9SEric Biggers 
2353fda4c61SEric Biggers 	desc->data_size = cpu_to_le64(inode->i_size);
2363fda4c61SEric Biggers 
2373fda4c61SEric Biggers 	/* Prepare the Merkle tree parameters */
2383fda4c61SEric Biggers 	err = fsverity_init_merkle_tree_params(&params, inode,
2393fda4c61SEric Biggers 					       arg->hash_algorithm,
2403fda4c61SEric Biggers 					       desc->log_blocksize,
2413fda4c61SEric Biggers 					       desc->salt, desc->salt_size);
2423fda4c61SEric Biggers 	if (err)
2433fda4c61SEric Biggers 		goto out;
2443fda4c61SEric Biggers 
2453fda4c61SEric Biggers 	/*
2463fda4c61SEric Biggers 	 * Start enabling verity on this file, serialized by the inode lock.
2473fda4c61SEric Biggers 	 * Fail if verity is already enabled or is already being enabled.
2483fda4c61SEric Biggers 	 */
2493fda4c61SEric Biggers 	inode_lock(inode);
2503fda4c61SEric Biggers 	if (IS_VERITY(inode))
2513fda4c61SEric Biggers 		err = -EEXIST;
2523fda4c61SEric Biggers 	else
2533fda4c61SEric Biggers 		err = vops->begin_enable_verity(filp);
2543fda4c61SEric Biggers 	inode_unlock(inode);
2553fda4c61SEric Biggers 	if (err)
2563fda4c61SEric Biggers 		goto out;
2573fda4c61SEric Biggers 
2583fda4c61SEric Biggers 	/*
2593fda4c61SEric Biggers 	 * Build the Merkle tree.  Don't hold the inode lock during this, since
2603fda4c61SEric Biggers 	 * on huge files this may take a very long time and we don't want to
2613fda4c61SEric Biggers 	 * force unrelated syscalls like chown() to block forever.  We don't
2623fda4c61SEric Biggers 	 * need the inode lock here because deny_write_access() already prevents
2633fda4c61SEric Biggers 	 * the file from being written to or truncated, and we still serialize
2643fda4c61SEric Biggers 	 * ->begin_enable_verity() and ->end_enable_verity() using the inode
2653fda4c61SEric Biggers 	 * lock and only allow one process to be here at a time on a given file.
2663fda4c61SEric Biggers 	 */
2673fda4c61SEric Biggers 	pr_debug("Building Merkle tree...\n");
2683fda4c61SEric Biggers 	BUILD_BUG_ON(sizeof(desc->root_hash) < FS_VERITY_MAX_DIGEST_SIZE);
269c22415d3SEric Biggers 	err = build_merkle_tree(filp, &params, desc->root_hash);
2703fda4c61SEric Biggers 	if (err) {
2713fda4c61SEric Biggers 		fsverity_err(inode, "Error %d building Merkle tree", err);
2723fda4c61SEric Biggers 		goto rollback;
2733fda4c61SEric Biggers 	}
2743fda4c61SEric Biggers 	pr_debug("Done building Merkle tree.  Root hash is %s:%*phN\n",
2753fda4c61SEric Biggers 		 params.hash_alg->name, params.digest_size, desc->root_hash);
2763fda4c61SEric Biggers 
2773fda4c61SEric Biggers 	/*
2783fda4c61SEric Biggers 	 * Create the fsverity_info.  Don't bother trying to save work by
2793fda4c61SEric Biggers 	 * reusing the merkle_tree_params from above.  Instead, just create the
2803fda4c61SEric Biggers 	 * fsverity_info from the fsverity_descriptor as if it were just loaded
2813fda4c61SEric Biggers 	 * from disk.  This is simpler, and it serves as an extra check that the
2823fda4c61SEric Biggers 	 * metadata we're writing is valid before actually enabling verity.
2833fda4c61SEric Biggers 	 */
2843fda4c61SEric Biggers 	vi = fsverity_create_info(inode, desc, desc_size);
2853fda4c61SEric Biggers 	if (IS_ERR(vi)) {
2863fda4c61SEric Biggers 		err = PTR_ERR(vi);
2873fda4c61SEric Biggers 		goto rollback;
2883fda4c61SEric Biggers 	}
2893fda4c61SEric Biggers 
290432434c9SEric Biggers 	if (arg->sig_size)
291432434c9SEric Biggers 		pr_debug("Storing a %u-byte PKCS#7 signature alongside the file\n",
292432434c9SEric Biggers 			 arg->sig_size);
293432434c9SEric Biggers 
2943fda4c61SEric Biggers 	/*
2953fda4c61SEric Biggers 	 * Tell the filesystem to finish enabling verity on the file.
2963fda4c61SEric Biggers 	 * Serialized with ->begin_enable_verity() by the inode lock.
2973fda4c61SEric Biggers 	 */
2983fda4c61SEric Biggers 	inode_lock(inode);
2993fda4c61SEric Biggers 	err = vops->end_enable_verity(filp, desc, desc_size, params.tree_size);
3003fda4c61SEric Biggers 	inode_unlock(inode);
3013fda4c61SEric Biggers 	if (err) {
3023fda4c61SEric Biggers 		fsverity_err(inode, "%ps() failed with err %d",
3033fda4c61SEric Biggers 			     vops->end_enable_verity, err);
3043fda4c61SEric Biggers 		fsverity_free_info(vi);
3053fda4c61SEric Biggers 	} else if (WARN_ON(!IS_VERITY(inode))) {
3063fda4c61SEric Biggers 		err = -EINVAL;
3073fda4c61SEric Biggers 		fsverity_free_info(vi);
3083fda4c61SEric Biggers 	} else {
3093fda4c61SEric Biggers 		/* Successfully enabled verity */
3103fda4c61SEric Biggers 
3113fda4c61SEric Biggers 		/*
3123fda4c61SEric Biggers 		 * Readers can start using ->i_verity_info immediately, so it
3133fda4c61SEric Biggers 		 * can't be rolled back once set.  So don't set it until just
3143fda4c61SEric Biggers 		 * after the filesystem has successfully enabled verity.
3153fda4c61SEric Biggers 		 */
3163fda4c61SEric Biggers 		fsverity_set_info(inode, vi);
3173fda4c61SEric Biggers 	}
3183fda4c61SEric Biggers out:
3193fda4c61SEric Biggers 	kfree(params.hashstate);
3203fda4c61SEric Biggers 	kfree(desc);
3213fda4c61SEric Biggers 	return err;
3223fda4c61SEric Biggers 
3233fda4c61SEric Biggers rollback:
3243fda4c61SEric Biggers 	inode_lock(inode);
3253fda4c61SEric Biggers 	(void)vops->end_enable_verity(filp, NULL, 0, params.tree_size);
3263fda4c61SEric Biggers 	inode_unlock(inode);
3273fda4c61SEric Biggers 	goto out;
3283fda4c61SEric Biggers }
3293fda4c61SEric Biggers 
3303fda4c61SEric Biggers /**
3313fda4c61SEric Biggers  * fsverity_ioctl_enable() - enable verity on a file
3326377a38bSEric Biggers  * @filp: file to enable verity on
3336377a38bSEric Biggers  * @uarg: user pointer to fsverity_enable_arg
3343fda4c61SEric Biggers  *
3353fda4c61SEric Biggers  * Enable fs-verity on a file.  See the "FS_IOC_ENABLE_VERITY" section of
3363fda4c61SEric Biggers  * Documentation/filesystems/fsverity.rst for the documentation.
3373fda4c61SEric Biggers  *
3383fda4c61SEric Biggers  * Return: 0 on success, -errno on failure
3393fda4c61SEric Biggers  */
3403fda4c61SEric Biggers int fsverity_ioctl_enable(struct file *filp, const void __user *uarg)
3413fda4c61SEric Biggers {
3423fda4c61SEric Biggers 	struct inode *inode = file_inode(filp);
3433fda4c61SEric Biggers 	struct fsverity_enable_arg arg;
3443fda4c61SEric Biggers 	int err;
3453fda4c61SEric Biggers 
3463fda4c61SEric Biggers 	if (copy_from_user(&arg, uarg, sizeof(arg)))
3473fda4c61SEric Biggers 		return -EFAULT;
3483fda4c61SEric Biggers 
3493fda4c61SEric Biggers 	if (arg.version != 1)
3503fda4c61SEric Biggers 		return -EINVAL;
3513fda4c61SEric Biggers 
3523fda4c61SEric Biggers 	if (arg.__reserved1 ||
3533fda4c61SEric Biggers 	    memchr_inv(arg.__reserved2, 0, sizeof(arg.__reserved2)))
3543fda4c61SEric Biggers 		return -EINVAL;
3553fda4c61SEric Biggers 
3563fda4c61SEric Biggers 	if (arg.block_size != PAGE_SIZE)
3573fda4c61SEric Biggers 		return -EINVAL;
3583fda4c61SEric Biggers 
359c593642cSPankaj Bharadiya 	if (arg.salt_size > sizeof_field(struct fsverity_descriptor, salt))
3603fda4c61SEric Biggers 		return -EMSGSIZE;
3613fda4c61SEric Biggers 
362432434c9SEric Biggers 	if (arg.sig_size > FS_VERITY_MAX_SIGNATURE_SIZE)
363432434c9SEric Biggers 		return -EMSGSIZE;
3643fda4c61SEric Biggers 
3653fda4c61SEric Biggers 	/*
3663fda4c61SEric Biggers 	 * Require a regular file with write access.  But the actual fd must
3673fda4c61SEric Biggers 	 * still be readonly so that we can lock out all writers.  This is
3683fda4c61SEric Biggers 	 * needed to guarantee that no writable fds exist to the file once it
3693fda4c61SEric Biggers 	 * has verity enabled, and to stabilize the data being hashed.
3703fda4c61SEric Biggers 	 */
3713fda4c61SEric Biggers 
3723fda4c61SEric Biggers 	err = inode_permission(inode, MAY_WRITE);
3733fda4c61SEric Biggers 	if (err)
3743fda4c61SEric Biggers 		return err;
3753fda4c61SEric Biggers 
3763fda4c61SEric Biggers 	if (IS_APPEND(inode))
3773fda4c61SEric Biggers 		return -EPERM;
3783fda4c61SEric Biggers 
3793fda4c61SEric Biggers 	if (S_ISDIR(inode->i_mode))
3803fda4c61SEric Biggers 		return -EISDIR;
3813fda4c61SEric Biggers 
3823fda4c61SEric Biggers 	if (!S_ISREG(inode->i_mode))
3833fda4c61SEric Biggers 		return -EINVAL;
3843fda4c61SEric Biggers 
3853fda4c61SEric Biggers 	err = mnt_want_write_file(filp);
3863fda4c61SEric Biggers 	if (err) /* -EROFS */
3873fda4c61SEric Biggers 		return err;
3883fda4c61SEric Biggers 
3893fda4c61SEric Biggers 	err = deny_write_access(filp);
3903fda4c61SEric Biggers 	if (err) /* -ETXTBSY */
3913fda4c61SEric Biggers 		goto out_drop_write;
3923fda4c61SEric Biggers 
3933fda4c61SEric Biggers 	err = enable_verity(filp, &arg);
3943fda4c61SEric Biggers 	if (err)
3953fda4c61SEric Biggers 		goto out_allow_write_access;
3963fda4c61SEric Biggers 
3973fda4c61SEric Biggers 	/*
3983fda4c61SEric Biggers 	 * Some pages of the file may have been evicted from pagecache after
3993fda4c61SEric Biggers 	 * being used in the Merkle tree construction, then read into pagecache
4003fda4c61SEric Biggers 	 * again by another process reading from the file concurrently.  Since
4013fda4c61SEric Biggers 	 * these pages didn't undergo verification against the file measurement
4023fda4c61SEric Biggers 	 * which fs-verity now claims to be enforcing, we have to wipe the
4033fda4c61SEric Biggers 	 * pagecache to ensure that all future reads are verified.
4043fda4c61SEric Biggers 	 */
4053fda4c61SEric Biggers 	filemap_write_and_wait(inode->i_mapping);
4063fda4c61SEric Biggers 	invalidate_inode_pages2(inode->i_mapping);
4073fda4c61SEric Biggers 
4083fda4c61SEric Biggers 	/*
4093fda4c61SEric Biggers 	 * allow_write_access() is needed to pair with deny_write_access().
4103fda4c61SEric Biggers 	 * Regardless, the filesystem won't allow writing to verity files.
4113fda4c61SEric Biggers 	 */
4123fda4c61SEric Biggers out_allow_write_access:
4133fda4c61SEric Biggers 	allow_write_access(filp);
4143fda4c61SEric Biggers out_drop_write:
4153fda4c61SEric Biggers 	mnt_drop_write_file(filp);
4163fda4c61SEric Biggers 	return err;
4173fda4c61SEric Biggers }
4183fda4c61SEric Biggers EXPORT_SYMBOL_GPL(fsverity_ioctl_enable);
419