xref: /OK3568_Linux_fs/kernel/fs/incfs/verity.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright 2020 Google LLC
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun /*
7*4882a593Smuzhiyun  * fs-verity integration into incfs
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * Since incfs has its own merkle tree implementation, most of fs-verity code
10*4882a593Smuzhiyun  * is not needed. The key part that is needed is the signature check, since
11*4882a593Smuzhiyun  * that is based on the private /proc/sys/fs/verity/require_signatures value
12*4882a593Smuzhiyun  * and a private keyring. Thus the first change is to modify verity code to
13*4882a593Smuzhiyun  * export a version of fsverity_verify_signature.
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * fs-verity integration then consists of the following modifications:
16*4882a593Smuzhiyun  *
17*4882a593Smuzhiyun  * 1. Add the (optional) verity signature to the incfs file format
18*4882a593Smuzhiyun  * 2. Add a pointer to the digest of the fs-verity descriptor struct to the
19*4882a593Smuzhiyun  *    data_file struct that incfs attaches to each file inode.
20*4882a593Smuzhiyun  * 3. Add the following ioclts:
21*4882a593Smuzhiyun  *  - FS_IOC_ENABLE_VERITY
22*4882a593Smuzhiyun  *  - FS_IOC_GETFLAGS
23*4882a593Smuzhiyun  *  - FS_IOC_MEASURE_VERITY
24*4882a593Smuzhiyun  * 4. When FS_IOC_ENABLE_VERITY is called on a non-verity file, the
25*4882a593Smuzhiyun  *    fs-verity descriptor struct is populated and digested. If it passes the
26*4882a593Smuzhiyun  *    signature check or the signature is NULL and
27*4882a593Smuzhiyun  *    fs.verity.require_signatures=0, then the S_VERITY flag is set and the
28*4882a593Smuzhiyun  *    xattr incfs.verity is set. If the signature is non-NULL, an
29*4882a593Smuzhiyun  *    INCFS_MD_VERITY_SIGNATURE is added to the backing file containing the
30*4882a593Smuzhiyun  *    signature.
31*4882a593Smuzhiyun  * 5. When a file with an incfs.verity xattr's inode is initialized, the
32*4882a593Smuzhiyun  *    inode’s S_VERITY flag is set.
33*4882a593Smuzhiyun  * 6. When a file with the S_VERITY flag set on its inode is opened, the
34*4882a593Smuzhiyun  *    data_file is checked for its verity digest. If the file doesn’t have a
35*4882a593Smuzhiyun  *    digest, the file’s digest is calculated as above, checked, and set, or the
36*4882a593Smuzhiyun  *    open is denied if it is not valid.
37*4882a593Smuzhiyun  * 7. FS_IOC_GETFLAGS simply returns the value of the S_VERITY flag
38*4882a593Smuzhiyun  * 8. FS_IOC_MEASURE_VERITY simply returns the cached digest
39*4882a593Smuzhiyun  * 9. The final complication is that if FS_IOC_ENABLE_VERITY is called on a file
40*4882a593Smuzhiyun  *    which doesn’t have a merkle tree, the merkle tree is calculated before the
41*4882a593Smuzhiyun  *    rest of the process is completed.
42*4882a593Smuzhiyun  */
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun #include <crypto/hash.h>
45*4882a593Smuzhiyun #include <crypto/sha.h>
46*4882a593Smuzhiyun #include <linux/fsverity.h>
47*4882a593Smuzhiyun #include <linux/mount.h>
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun #include "verity.h"
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #include "data_mgmt.h"
52*4882a593Smuzhiyun #include "format.h"
53*4882a593Smuzhiyun #include "integrity.h"
54*4882a593Smuzhiyun #include "vfs.h"
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun #define FS_VERITY_MAX_SIGNATURE_SIZE	16128
57*4882a593Smuzhiyun 
incfs_get_root_hash(struct file * filp,u8 * root_hash)58*4882a593Smuzhiyun static int incfs_get_root_hash(struct file *filp, u8 *root_hash)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun 	struct data_file *df = get_incfs_data_file(filp);
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 	if (!df)
63*4882a593Smuzhiyun 		return -EINVAL;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	memcpy(root_hash, df->df_hash_tree->root_hash,
66*4882a593Smuzhiyun 	       df->df_hash_tree->alg->digest_size);
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	return 0;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun 
incfs_end_enable_verity(struct file * filp,u8 * sig,size_t sig_size)71*4882a593Smuzhiyun static int incfs_end_enable_verity(struct file *filp, u8 *sig, size_t sig_size)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun 	struct inode *inode = file_inode(filp);
74*4882a593Smuzhiyun 	struct mem_range signature = {
75*4882a593Smuzhiyun 		.data = sig,
76*4882a593Smuzhiyun 		.len = sig_size,
77*4882a593Smuzhiyun 	};
78*4882a593Smuzhiyun 	struct data_file *df = get_incfs_data_file(filp);
79*4882a593Smuzhiyun 	struct backing_file_context *bfc;
80*4882a593Smuzhiyun 	int error;
81*4882a593Smuzhiyun 	struct incfs_df_verity_signature *vs = NULL;
82*4882a593Smuzhiyun 	loff_t offset;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	if (!df || !df->df_backing_file_context)
85*4882a593Smuzhiyun 		return -EFSCORRUPTED;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	if (sig) {
88*4882a593Smuzhiyun 		vs = kzalloc(sizeof(*vs), GFP_NOFS);
89*4882a593Smuzhiyun 		if (!vs)
90*4882a593Smuzhiyun 			return -ENOMEM;
91*4882a593Smuzhiyun 	}
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	bfc = df->df_backing_file_context;
94*4882a593Smuzhiyun 	error = mutex_lock_interruptible(&bfc->bc_mutex);
95*4882a593Smuzhiyun 	if (error)
96*4882a593Smuzhiyun 		goto out;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	error = incfs_write_verity_signature_to_backing_file(bfc, signature,
99*4882a593Smuzhiyun 							     &offset);
100*4882a593Smuzhiyun 	mutex_unlock(&bfc->bc_mutex);
101*4882a593Smuzhiyun 	if (error)
102*4882a593Smuzhiyun 		goto out;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	/*
105*4882a593Smuzhiyun 	 * Set verity xattr so we can set S_VERITY without opening backing file
106*4882a593Smuzhiyun 	 */
107*4882a593Smuzhiyun 	error = vfs_setxattr(bfc->bc_file->f_path.dentry,
108*4882a593Smuzhiyun 			     INCFS_XATTR_VERITY_NAME, NULL, 0, XATTR_CREATE);
109*4882a593Smuzhiyun 	if (error) {
110*4882a593Smuzhiyun 		pr_warn("incfs: error setting verity xattr: %d\n", error);
111*4882a593Smuzhiyun 		goto out;
112*4882a593Smuzhiyun 	}
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	if (sig) {
115*4882a593Smuzhiyun 		*vs = (struct incfs_df_verity_signature) {
116*4882a593Smuzhiyun 			.size = signature.len,
117*4882a593Smuzhiyun 			.offset = offset,
118*4882a593Smuzhiyun 		};
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 		df->df_verity_signature = vs;
121*4882a593Smuzhiyun 		vs = NULL;
122*4882a593Smuzhiyun 	}
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	inode_set_flags(inode, S_VERITY, S_VERITY);
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun out:
127*4882a593Smuzhiyun 	kfree(vs);
128*4882a593Smuzhiyun 	return error;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun 
incfs_compute_file_digest(struct incfs_hash_alg * alg,struct fsverity_descriptor * desc,u8 * digest)131*4882a593Smuzhiyun static int incfs_compute_file_digest(struct incfs_hash_alg *alg,
132*4882a593Smuzhiyun 				struct fsverity_descriptor *desc,
133*4882a593Smuzhiyun 				u8 *digest)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun 	SHASH_DESC_ON_STACK(d, alg->shash);
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	d->tfm = alg->shash;
138*4882a593Smuzhiyun 	return crypto_shash_digest(d, (u8 *)desc, sizeof(*desc), digest);
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
incfs_convert_fsverity_hash_alg(int hash_alg)141*4882a593Smuzhiyun static enum incfs_hash_tree_algorithm incfs_convert_fsverity_hash_alg(
142*4882a593Smuzhiyun 								int hash_alg)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun 	switch (hash_alg) {
145*4882a593Smuzhiyun 	case FS_VERITY_HASH_ALG_SHA256:
146*4882a593Smuzhiyun 		return INCFS_HASH_TREE_SHA256;
147*4882a593Smuzhiyun 	default:
148*4882a593Smuzhiyun 		return -EINVAL;
149*4882a593Smuzhiyun 	}
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun 
incfs_get_verity_digest(struct inode * inode)152*4882a593Smuzhiyun static struct mem_range incfs_get_verity_digest(struct inode *inode)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun 	struct inode_info *node = get_incfs_node(inode);
155*4882a593Smuzhiyun 	struct data_file *df;
156*4882a593Smuzhiyun 	struct mem_range verity_file_digest;
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	if (!node) {
159*4882a593Smuzhiyun 		pr_warn("Invalid inode\n");
160*4882a593Smuzhiyun 		return range(NULL, 0);
161*4882a593Smuzhiyun 	}
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	df = node->n_file;
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	/*
166*4882a593Smuzhiyun 	 * Pairs with the cmpxchg_release() in incfs_set_verity_digest().
167*4882a593Smuzhiyun 	 * I.e., another task may publish ->df_verity_file_digest concurrently,
168*4882a593Smuzhiyun 	 * executing a RELEASE barrier.  We need to use smp_load_acquire() here
169*4882a593Smuzhiyun 	 * to safely ACQUIRE the memory the other task published.
170*4882a593Smuzhiyun 	 */
171*4882a593Smuzhiyun 	verity_file_digest.data = smp_load_acquire(
172*4882a593Smuzhiyun 					&df->df_verity_file_digest.data);
173*4882a593Smuzhiyun 	verity_file_digest.len = df->df_verity_file_digest.len;
174*4882a593Smuzhiyun 	return verity_file_digest;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun 
incfs_set_verity_digest(struct inode * inode,struct mem_range verity_file_digest)177*4882a593Smuzhiyun static void incfs_set_verity_digest(struct inode *inode,
178*4882a593Smuzhiyun 				     struct mem_range verity_file_digest)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun 	struct inode_info *node = get_incfs_node(inode);
181*4882a593Smuzhiyun 	struct data_file *df;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	if (!node) {
184*4882a593Smuzhiyun 		pr_warn("Invalid inode\n");
185*4882a593Smuzhiyun 		kfree(verity_file_digest.data);
186*4882a593Smuzhiyun 		return;
187*4882a593Smuzhiyun 	}
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	df = node->n_file;
190*4882a593Smuzhiyun 	df->df_verity_file_digest.len = verity_file_digest.len;
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	/*
193*4882a593Smuzhiyun 	 * Multiple tasks may race to set ->df_verity_file_digest.data, so use
194*4882a593Smuzhiyun 	 * cmpxchg_release().  This pairs with the smp_load_acquire() in
195*4882a593Smuzhiyun 	 * incfs_get_verity_digest().  I.e., here we publish
196*4882a593Smuzhiyun 	 * ->df_verity_file_digest.data, with a RELEASE barrier so that other
197*4882a593Smuzhiyun 	 * tasks can ACQUIRE it.
198*4882a593Smuzhiyun 	 */
199*4882a593Smuzhiyun 	if (cmpxchg_release(&df->df_verity_file_digest.data, NULL,
200*4882a593Smuzhiyun 			    verity_file_digest.data) != NULL)
201*4882a593Smuzhiyun 		/* Lost the race, so free the file_digest we allocated. */
202*4882a593Smuzhiyun 		kfree(verity_file_digest.data);
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun /*
206*4882a593Smuzhiyun  * Calculate the digest of the fsverity_descriptor. The signature (if present)
207*4882a593Smuzhiyun  * is also checked.
208*4882a593Smuzhiyun  */
incfs_calc_verity_digest_from_desc(const struct inode * inode,struct fsverity_descriptor * desc,u8 * signature,size_t sig_size)209*4882a593Smuzhiyun static struct mem_range incfs_calc_verity_digest_from_desc(
210*4882a593Smuzhiyun 					const struct inode *inode,
211*4882a593Smuzhiyun 					struct fsverity_descriptor *desc,
212*4882a593Smuzhiyun 					u8 *signature, size_t sig_size)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	enum incfs_hash_tree_algorithm incfs_hash_alg;
215*4882a593Smuzhiyun 	struct mem_range verity_file_digest;
216*4882a593Smuzhiyun 	int err;
217*4882a593Smuzhiyun 	struct incfs_hash_alg *hash_alg;
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	incfs_hash_alg = incfs_convert_fsverity_hash_alg(desc->hash_algorithm);
220*4882a593Smuzhiyun 	if (incfs_hash_alg < 0)
221*4882a593Smuzhiyun 		return range(ERR_PTR(incfs_hash_alg), 0);
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	hash_alg = incfs_get_hash_alg(incfs_hash_alg);
224*4882a593Smuzhiyun 	if (IS_ERR(hash_alg))
225*4882a593Smuzhiyun 		return range((u8 *)hash_alg, 0);
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	verity_file_digest = range(kzalloc(hash_alg->digest_size, GFP_KERNEL),
228*4882a593Smuzhiyun 				   hash_alg->digest_size);
229*4882a593Smuzhiyun 	if (!verity_file_digest.data)
230*4882a593Smuzhiyun 		return range(ERR_PTR(-ENOMEM), 0);
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 	err = incfs_compute_file_digest(hash_alg, desc,
233*4882a593Smuzhiyun 					verity_file_digest.data);
234*4882a593Smuzhiyun 	if (err) {
235*4882a593Smuzhiyun 		pr_err("Error %d computing file digest", err);
236*4882a593Smuzhiyun 		goto out;
237*4882a593Smuzhiyun 	}
238*4882a593Smuzhiyun 	pr_debug("Computed file digest: %s:%*phN\n",
239*4882a593Smuzhiyun 		 hash_alg->name, (int) verity_file_digest.len,
240*4882a593Smuzhiyun 		 verity_file_digest.data);
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	err = __fsverity_verify_signature(inode, signature, sig_size,
243*4882a593Smuzhiyun 					  verity_file_digest.data,
244*4882a593Smuzhiyun 					  desc->hash_algorithm);
245*4882a593Smuzhiyun out:
246*4882a593Smuzhiyun 	if (err) {
247*4882a593Smuzhiyun 		kfree(verity_file_digest.data);
248*4882a593Smuzhiyun 		verity_file_digest = range(ERR_PTR(err), 0);
249*4882a593Smuzhiyun 	}
250*4882a593Smuzhiyun 	return verity_file_digest;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun 
incfs_get_fsverity_descriptor(struct file * filp,int hash_algorithm)253*4882a593Smuzhiyun static struct fsverity_descriptor *incfs_get_fsverity_descriptor(
254*4882a593Smuzhiyun 					struct file *filp, int hash_algorithm)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun 	struct inode *inode = file_inode(filp);
257*4882a593Smuzhiyun 	struct fsverity_descriptor *desc = kzalloc(sizeof(*desc), GFP_KERNEL);
258*4882a593Smuzhiyun 	int err;
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	if (!desc)
261*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	*desc = (struct fsverity_descriptor) {
264*4882a593Smuzhiyun 		.version = 1,
265*4882a593Smuzhiyun 		.hash_algorithm = hash_algorithm,
266*4882a593Smuzhiyun 		.log_blocksize = ilog2(INCFS_DATA_FILE_BLOCK_SIZE),
267*4882a593Smuzhiyun 		.data_size = cpu_to_le64(inode->i_size),
268*4882a593Smuzhiyun 	};
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	err = incfs_get_root_hash(filp, desc->root_hash);
271*4882a593Smuzhiyun 	if (err) {
272*4882a593Smuzhiyun 		kfree(desc);
273*4882a593Smuzhiyun 		return ERR_PTR(err);
274*4882a593Smuzhiyun 	}
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	return desc;
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun 
incfs_calc_verity_digest(struct inode * inode,struct file * filp,u8 * signature,size_t signature_size,int hash_algorithm)279*4882a593Smuzhiyun static struct mem_range incfs_calc_verity_digest(
280*4882a593Smuzhiyun 					struct inode *inode, struct file *filp,
281*4882a593Smuzhiyun 					u8 *signature, size_t signature_size,
282*4882a593Smuzhiyun 					int hash_algorithm)
283*4882a593Smuzhiyun {
284*4882a593Smuzhiyun 	struct fsverity_descriptor *desc = incfs_get_fsverity_descriptor(filp,
285*4882a593Smuzhiyun 							hash_algorithm);
286*4882a593Smuzhiyun 	struct mem_range verity_file_digest;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	if (IS_ERR(desc))
289*4882a593Smuzhiyun 		return range((u8 *)desc, 0);
290*4882a593Smuzhiyun 	verity_file_digest = incfs_calc_verity_digest_from_desc(inode, desc,
291*4882a593Smuzhiyun 						signature, signature_size);
292*4882a593Smuzhiyun 	kfree(desc);
293*4882a593Smuzhiyun 	return verity_file_digest;
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun 
incfs_build_merkle_tree(struct file * f,struct data_file * df,struct backing_file_context * bfc,struct mtree * hash_tree,loff_t hash_offset,struct incfs_hash_alg * alg,struct mem_range hash)296*4882a593Smuzhiyun static int incfs_build_merkle_tree(struct file *f, struct data_file *df,
297*4882a593Smuzhiyun 			     struct backing_file_context *bfc,
298*4882a593Smuzhiyun 			     struct mtree *hash_tree, loff_t hash_offset,
299*4882a593Smuzhiyun 			     struct incfs_hash_alg *alg, struct mem_range hash)
300*4882a593Smuzhiyun {
301*4882a593Smuzhiyun 	int error = 0;
302*4882a593Smuzhiyun 	int limit, lvl, i, result;
303*4882a593Smuzhiyun 	struct mem_range buf = {.len = INCFS_DATA_FILE_BLOCK_SIZE};
304*4882a593Smuzhiyun 	struct mem_range tmp = {.len = 2 * INCFS_DATA_FILE_BLOCK_SIZE};
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 	buf.data = (u8 *)__get_free_pages(GFP_NOFS, get_order(buf.len));
307*4882a593Smuzhiyun 	tmp.data = (u8 *)__get_free_pages(GFP_NOFS, get_order(tmp.len));
308*4882a593Smuzhiyun 	if (!buf.data || !tmp.data) {
309*4882a593Smuzhiyun 		error = -ENOMEM;
310*4882a593Smuzhiyun 		goto out;
311*4882a593Smuzhiyun 	}
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	/*
314*4882a593Smuzhiyun 	 * lvl - 1 is the level we are reading, lvl the level we are writing
315*4882a593Smuzhiyun 	 * lvl == -1 means actual blocks
316*4882a593Smuzhiyun 	 * lvl == hash_tree->depth means root hash
317*4882a593Smuzhiyun 	 */
318*4882a593Smuzhiyun 	limit = df->df_data_block_count;
319*4882a593Smuzhiyun 	for (lvl = 0; lvl <= hash_tree->depth; lvl++) {
320*4882a593Smuzhiyun 		for (i = 0; i < limit; ++i) {
321*4882a593Smuzhiyun 			loff_t hash_level_offset;
322*4882a593Smuzhiyun 			struct mem_range partial_buf = buf;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 			if (lvl == 0)
325*4882a593Smuzhiyun 				result = incfs_read_data_file_block(partial_buf,
326*4882a593Smuzhiyun 						f, i, tmp, NULL);
327*4882a593Smuzhiyun 			else {
328*4882a593Smuzhiyun 				hash_level_offset = hash_offset +
329*4882a593Smuzhiyun 				       hash_tree->hash_level_suboffset[lvl - 1];
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 				result = incfs_kread(bfc, partial_buf.data,
332*4882a593Smuzhiyun 						partial_buf.len,
333*4882a593Smuzhiyun 						hash_level_offset + i *
334*4882a593Smuzhiyun 						INCFS_DATA_FILE_BLOCK_SIZE);
335*4882a593Smuzhiyun 			}
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 			if (result < 0) {
338*4882a593Smuzhiyun 				error = result;
339*4882a593Smuzhiyun 				goto out;
340*4882a593Smuzhiyun 			}
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 			partial_buf.len = result;
343*4882a593Smuzhiyun 			error = incfs_calc_digest(alg, partial_buf, hash);
344*4882a593Smuzhiyun 			if (error)
345*4882a593Smuzhiyun 				goto out;
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 			/*
348*4882a593Smuzhiyun 			 * last level - only one hash to take and it is stored
349*4882a593Smuzhiyun 			 * in the incfs signature record
350*4882a593Smuzhiyun 			 */
351*4882a593Smuzhiyun 			if (lvl == hash_tree->depth)
352*4882a593Smuzhiyun 				break;
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 			hash_level_offset = hash_offset +
355*4882a593Smuzhiyun 				hash_tree->hash_level_suboffset[lvl];
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 			result = incfs_kwrite(bfc, hash.data, hash.len,
358*4882a593Smuzhiyun 					hash_level_offset + hash.len * i);
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 			if (result < 0) {
361*4882a593Smuzhiyun 				error = result;
362*4882a593Smuzhiyun 				goto out;
363*4882a593Smuzhiyun 			}
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 			if (result != hash.len) {
366*4882a593Smuzhiyun 				error = -EIO;
367*4882a593Smuzhiyun 				goto out;
368*4882a593Smuzhiyun 			}
369*4882a593Smuzhiyun 		}
370*4882a593Smuzhiyun 		limit = DIV_ROUND_UP(limit,
371*4882a593Smuzhiyun 				     INCFS_DATA_FILE_BLOCK_SIZE / hash.len);
372*4882a593Smuzhiyun 	}
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun out:
375*4882a593Smuzhiyun 	free_pages((unsigned long)tmp.data, get_order(tmp.len));
376*4882a593Smuzhiyun 	free_pages((unsigned long)buf.data, get_order(buf.len));
377*4882a593Smuzhiyun 	return error;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun /*
381*4882a593Smuzhiyun  * incfs files have a signature record that is separate from the
382*4882a593Smuzhiyun  * verity_signature record. The signature record does not actually contain a
383*4882a593Smuzhiyun  * signature, rather it contains the size/offset of the hash tree, and a binary
384*4882a593Smuzhiyun  * blob which contains the root hash and potentially a signature.
385*4882a593Smuzhiyun  *
386*4882a593Smuzhiyun  * If the file was created with a signature record, then this function simply
387*4882a593Smuzhiyun  * returns.
388*4882a593Smuzhiyun  *
389*4882a593Smuzhiyun  * Otherwise it will create a signature record with a minimal binary blob as
390*4882a593Smuzhiyun  * defined by the structure below, create space for the hash tree and then
391*4882a593Smuzhiyun  * populate it using incfs_build_merkle_tree
392*4882a593Smuzhiyun  */
incfs_add_signature_record(struct file * f)393*4882a593Smuzhiyun static int incfs_add_signature_record(struct file *f)
394*4882a593Smuzhiyun {
395*4882a593Smuzhiyun 	/* See incfs_parse_signature */
396*4882a593Smuzhiyun 	struct {
397*4882a593Smuzhiyun 		__le32 version;
398*4882a593Smuzhiyun 		__le32 size_of_hash_info_section;
399*4882a593Smuzhiyun 		struct {
400*4882a593Smuzhiyun 			__le32 hash_algorithm;
401*4882a593Smuzhiyun 			u8 log2_blocksize;
402*4882a593Smuzhiyun 			__le32 salt_size;
403*4882a593Smuzhiyun 			u8 salt[0];
404*4882a593Smuzhiyun 			__le32 hash_size;
405*4882a593Smuzhiyun 			u8 root_hash[32];
406*4882a593Smuzhiyun 		} __packed hash_section;
407*4882a593Smuzhiyun 		__le32 size_of_signing_info_section;
408*4882a593Smuzhiyun 		u8 signing_info_section[0];
409*4882a593Smuzhiyun 	} __packed sig = {
410*4882a593Smuzhiyun 		.version = cpu_to_le32(INCFS_SIGNATURE_VERSION),
411*4882a593Smuzhiyun 		.size_of_hash_info_section =
412*4882a593Smuzhiyun 			cpu_to_le32(sizeof(sig.hash_section)),
413*4882a593Smuzhiyun 		.hash_section = {
414*4882a593Smuzhiyun 			.hash_algorithm = cpu_to_le32(INCFS_HASH_TREE_SHA256),
415*4882a593Smuzhiyun 			.log2_blocksize = ilog2(INCFS_DATA_FILE_BLOCK_SIZE),
416*4882a593Smuzhiyun 			.hash_size = cpu_to_le32(SHA256_DIGEST_SIZE),
417*4882a593Smuzhiyun 		},
418*4882a593Smuzhiyun 	};
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 	struct data_file *df = get_incfs_data_file(f);
421*4882a593Smuzhiyun 	struct mtree *hash_tree = NULL;
422*4882a593Smuzhiyun 	struct backing_file_context *bfc;
423*4882a593Smuzhiyun 	int error;
424*4882a593Smuzhiyun 	loff_t hash_offset, sig_offset;
425*4882a593Smuzhiyun 	struct incfs_hash_alg *alg = incfs_get_hash_alg(INCFS_HASH_TREE_SHA256);
426*4882a593Smuzhiyun 	u8 hash_buf[INCFS_MAX_HASH_SIZE];
427*4882a593Smuzhiyun 	int hash_size = alg->digest_size;
428*4882a593Smuzhiyun 	struct mem_range hash = range(hash_buf, hash_size);
429*4882a593Smuzhiyun 	int result;
430*4882a593Smuzhiyun 	struct incfs_df_signature *signature = NULL;
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 	if (!df)
433*4882a593Smuzhiyun 		return -EINVAL;
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	if (df->df_header_flags & INCFS_FILE_MAPPED)
436*4882a593Smuzhiyun 		return -EINVAL;
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	/* Already signed? */
439*4882a593Smuzhiyun 	if (df->df_signature && df->df_hash_tree)
440*4882a593Smuzhiyun 		return 0;
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	if (df->df_signature || df->df_hash_tree)
443*4882a593Smuzhiyun 		return -EFSCORRUPTED;
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun 	/* Add signature metadata record to file */
446*4882a593Smuzhiyun 	hash_tree = incfs_alloc_mtree(range((u8 *)&sig, sizeof(sig)),
447*4882a593Smuzhiyun 				      df->df_data_block_count);
448*4882a593Smuzhiyun 	if (IS_ERR(hash_tree))
449*4882a593Smuzhiyun 		return PTR_ERR(hash_tree);
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 	bfc = df->df_backing_file_context;
452*4882a593Smuzhiyun 	if (!bfc) {
453*4882a593Smuzhiyun 		error = -EFSCORRUPTED;
454*4882a593Smuzhiyun 		goto out;
455*4882a593Smuzhiyun 	}
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 	error = mutex_lock_interruptible(&bfc->bc_mutex);
458*4882a593Smuzhiyun 	if (error)
459*4882a593Smuzhiyun 		goto out;
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	error = incfs_write_signature_to_backing_file(bfc,
462*4882a593Smuzhiyun 				range((u8 *)&sig, sizeof(sig)),
463*4882a593Smuzhiyun 				hash_tree->hash_tree_area_size,
464*4882a593Smuzhiyun 				&hash_offset, &sig_offset);
465*4882a593Smuzhiyun 	mutex_unlock(&bfc->bc_mutex);
466*4882a593Smuzhiyun 	if (error)
467*4882a593Smuzhiyun 		goto out;
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	/* Populate merkle tree */
470*4882a593Smuzhiyun 	error = incfs_build_merkle_tree(f, df, bfc, hash_tree, hash_offset, alg,
471*4882a593Smuzhiyun 				  hash);
472*4882a593Smuzhiyun 	if (error)
473*4882a593Smuzhiyun 		goto out;
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	/* Update signature metadata record */
476*4882a593Smuzhiyun 	memcpy(sig.hash_section.root_hash, hash.data, alg->digest_size);
477*4882a593Smuzhiyun 	result = incfs_kwrite(bfc, &sig, sizeof(sig), sig_offset);
478*4882a593Smuzhiyun 	if (result < 0) {
479*4882a593Smuzhiyun 		error = result;
480*4882a593Smuzhiyun 		goto out;
481*4882a593Smuzhiyun 	}
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	if (result != sizeof(sig)) {
484*4882a593Smuzhiyun 		error = -EIO;
485*4882a593Smuzhiyun 		goto out;
486*4882a593Smuzhiyun 	}
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	/* Update in-memory records */
489*4882a593Smuzhiyun 	memcpy(hash_tree->root_hash, hash.data, alg->digest_size);
490*4882a593Smuzhiyun 	signature = kzalloc(sizeof(*signature), GFP_NOFS);
491*4882a593Smuzhiyun 	if (!signature) {
492*4882a593Smuzhiyun 		error = -ENOMEM;
493*4882a593Smuzhiyun 		goto out;
494*4882a593Smuzhiyun 	}
495*4882a593Smuzhiyun 	*signature = (struct incfs_df_signature) {
496*4882a593Smuzhiyun 		.hash_offset = hash_offset,
497*4882a593Smuzhiyun 		.hash_size = hash_tree->hash_tree_area_size,
498*4882a593Smuzhiyun 		.sig_offset = sig_offset,
499*4882a593Smuzhiyun 		.sig_size = sizeof(sig),
500*4882a593Smuzhiyun 	};
501*4882a593Smuzhiyun 	df->df_signature = signature;
502*4882a593Smuzhiyun 	signature = NULL;
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun 	/*
505*4882a593Smuzhiyun 	 * Use memory barrier to prevent readpage seeing the hash tree until
506*4882a593Smuzhiyun 	 * it's fully there
507*4882a593Smuzhiyun 	 */
508*4882a593Smuzhiyun 	smp_store_release(&df->df_hash_tree, hash_tree);
509*4882a593Smuzhiyun 	hash_tree = NULL;
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun out:
512*4882a593Smuzhiyun 	kfree(signature);
513*4882a593Smuzhiyun 	kfree(hash_tree);
514*4882a593Smuzhiyun 	return error;
515*4882a593Smuzhiyun }
516*4882a593Smuzhiyun 
incfs_enable_verity(struct file * filp,const struct fsverity_enable_arg * arg)517*4882a593Smuzhiyun static int incfs_enable_verity(struct file *filp,
518*4882a593Smuzhiyun 			 const struct fsverity_enable_arg *arg)
519*4882a593Smuzhiyun {
520*4882a593Smuzhiyun 	struct inode *inode = file_inode(filp);
521*4882a593Smuzhiyun 	struct data_file *df = get_incfs_data_file(filp);
522*4882a593Smuzhiyun 	u8 *signature = NULL;
523*4882a593Smuzhiyun 	struct mem_range verity_file_digest = range(NULL, 0);
524*4882a593Smuzhiyun 	int err;
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 	if (!df)
527*4882a593Smuzhiyun 		return -EFSCORRUPTED;
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 	err = mutex_lock_interruptible(&df->df_enable_verity);
530*4882a593Smuzhiyun 	if (err)
531*4882a593Smuzhiyun 		return err;
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun 	if (IS_VERITY(inode)) {
534*4882a593Smuzhiyun 		err = -EEXIST;
535*4882a593Smuzhiyun 		goto out;
536*4882a593Smuzhiyun 	}
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 	err = incfs_add_signature_record(filp);
539*4882a593Smuzhiyun 	if (err)
540*4882a593Smuzhiyun 		goto out;
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 	/* Get the signature if the user provided one */
543*4882a593Smuzhiyun 	if (arg->sig_size) {
544*4882a593Smuzhiyun 		signature = memdup_user(u64_to_user_ptr(arg->sig_ptr),
545*4882a593Smuzhiyun 					arg->sig_size);
546*4882a593Smuzhiyun 		if (IS_ERR(signature)) {
547*4882a593Smuzhiyun 			err = PTR_ERR(signature);
548*4882a593Smuzhiyun 			signature = NULL;
549*4882a593Smuzhiyun 			goto out;
550*4882a593Smuzhiyun 		}
551*4882a593Smuzhiyun 	}
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	verity_file_digest = incfs_calc_verity_digest(inode, filp, signature,
554*4882a593Smuzhiyun 					arg->sig_size, arg->hash_algorithm);
555*4882a593Smuzhiyun 	if (IS_ERR(verity_file_digest.data)) {
556*4882a593Smuzhiyun 		err = PTR_ERR(verity_file_digest.data);
557*4882a593Smuzhiyun 		verity_file_digest.data = NULL;
558*4882a593Smuzhiyun 		goto out;
559*4882a593Smuzhiyun 	}
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun 	err = incfs_end_enable_verity(filp, signature, arg->sig_size);
562*4882a593Smuzhiyun 	if (err)
563*4882a593Smuzhiyun 		goto out;
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 	/* Successfully enabled verity */
566*4882a593Smuzhiyun 	incfs_set_verity_digest(inode, verity_file_digest);
567*4882a593Smuzhiyun 	verity_file_digest.data = NULL;
568*4882a593Smuzhiyun out:
569*4882a593Smuzhiyun 	mutex_unlock(&df->df_enable_verity);
570*4882a593Smuzhiyun 	kfree(signature);
571*4882a593Smuzhiyun 	kfree(verity_file_digest.data);
572*4882a593Smuzhiyun 	if (err)
573*4882a593Smuzhiyun 		pr_err("%s failed with err %d\n", __func__, err);
574*4882a593Smuzhiyun 	return err;
575*4882a593Smuzhiyun }
576*4882a593Smuzhiyun 
incfs_ioctl_enable_verity(struct file * filp,const void __user * uarg)577*4882a593Smuzhiyun int incfs_ioctl_enable_verity(struct file *filp, const void __user *uarg)
578*4882a593Smuzhiyun {
579*4882a593Smuzhiyun 	struct inode *inode = file_inode(filp);
580*4882a593Smuzhiyun 	struct fsverity_enable_arg arg;
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun 	if (copy_from_user(&arg, uarg, sizeof(arg)))
583*4882a593Smuzhiyun 		return -EFAULT;
584*4882a593Smuzhiyun 
585*4882a593Smuzhiyun 	if (arg.version != 1)
586*4882a593Smuzhiyun 		return -EINVAL;
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun 	if (arg.__reserved1 ||
589*4882a593Smuzhiyun 	    memchr_inv(arg.__reserved2, 0, sizeof(arg.__reserved2)))
590*4882a593Smuzhiyun 		return -EINVAL;
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun 	if (arg.hash_algorithm != FS_VERITY_HASH_ALG_SHA256)
593*4882a593Smuzhiyun 		return -EINVAL;
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun 	if (arg.block_size != PAGE_SIZE)
596*4882a593Smuzhiyun 		return -EINVAL;
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun 	if (arg.salt_size)
599*4882a593Smuzhiyun 		return -EINVAL;
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 	if (arg.sig_size > FS_VERITY_MAX_SIGNATURE_SIZE)
602*4882a593Smuzhiyun 		return -EMSGSIZE;
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun 	if (S_ISDIR(inode->i_mode))
605*4882a593Smuzhiyun 		return -EISDIR;
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun 	if (!S_ISREG(inode->i_mode))
608*4882a593Smuzhiyun 		return -EINVAL;
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun 	return incfs_enable_verity(filp, &arg);
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun 
incfs_get_verity_signature(struct file * filp,size_t * sig_size)613*4882a593Smuzhiyun static u8 *incfs_get_verity_signature(struct file *filp, size_t *sig_size)
614*4882a593Smuzhiyun {
615*4882a593Smuzhiyun 	struct data_file *df = get_incfs_data_file(filp);
616*4882a593Smuzhiyun 	struct incfs_df_verity_signature *vs;
617*4882a593Smuzhiyun 	u8 *signature;
618*4882a593Smuzhiyun 	int res;
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun 	if (!df || !df->df_backing_file_context)
621*4882a593Smuzhiyun 		return ERR_PTR(-EFSCORRUPTED);
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	vs = df->df_verity_signature;
624*4882a593Smuzhiyun 	if (!vs) {
625*4882a593Smuzhiyun 		*sig_size = 0;
626*4882a593Smuzhiyun 		return NULL;
627*4882a593Smuzhiyun 	}
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun 	if (!vs->size) {
630*4882a593Smuzhiyun 		*sig_size = 0;
631*4882a593Smuzhiyun 		return ERR_PTR(-EFSCORRUPTED);
632*4882a593Smuzhiyun 	}
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun 	signature = kzalloc(vs->size, GFP_KERNEL);
635*4882a593Smuzhiyun 	if (!signature)
636*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 	res = incfs_kread(df->df_backing_file_context,
639*4882a593Smuzhiyun 			  signature, vs->size, vs->offset);
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun 	if (res < 0)
642*4882a593Smuzhiyun 		goto err_out;
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun 	if (res != vs->size) {
645*4882a593Smuzhiyun 		res = -EINVAL;
646*4882a593Smuzhiyun 		goto err_out;
647*4882a593Smuzhiyun 	}
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun 	*sig_size = vs->size;
650*4882a593Smuzhiyun 	return signature;
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun err_out:
653*4882a593Smuzhiyun 	kfree(signature);
654*4882a593Smuzhiyun 	return ERR_PTR(res);
655*4882a593Smuzhiyun }
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun /* Ensure data_file->df_verity_file_digest is populated */
ensure_verity_info(struct inode * inode,struct file * filp)658*4882a593Smuzhiyun static int ensure_verity_info(struct inode *inode, struct file *filp)
659*4882a593Smuzhiyun {
660*4882a593Smuzhiyun 	struct mem_range verity_file_digest;
661*4882a593Smuzhiyun 	u8 *signature = NULL;
662*4882a593Smuzhiyun 	size_t sig_size;
663*4882a593Smuzhiyun 	int err = 0;
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun 	/* See if this file's verity file digest is already cached */
666*4882a593Smuzhiyun 	verity_file_digest = incfs_get_verity_digest(inode);
667*4882a593Smuzhiyun 	if (verity_file_digest.data)
668*4882a593Smuzhiyun 		return 0;
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 	signature = incfs_get_verity_signature(filp, &sig_size);
671*4882a593Smuzhiyun 	if (IS_ERR(signature))
672*4882a593Smuzhiyun 		return PTR_ERR(signature);
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun 	verity_file_digest = incfs_calc_verity_digest(inode, filp, signature,
675*4882a593Smuzhiyun 						     sig_size,
676*4882a593Smuzhiyun 						     FS_VERITY_HASH_ALG_SHA256);
677*4882a593Smuzhiyun 	if (IS_ERR(verity_file_digest.data)) {
678*4882a593Smuzhiyun 		err = PTR_ERR(verity_file_digest.data);
679*4882a593Smuzhiyun 		goto out;
680*4882a593Smuzhiyun 	}
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	incfs_set_verity_digest(inode, verity_file_digest);
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun out:
685*4882a593Smuzhiyun 	kfree(signature);
686*4882a593Smuzhiyun 	return err;
687*4882a593Smuzhiyun }
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun /**
690*4882a593Smuzhiyun  * incfs_fsverity_file_open() - prepare to open a file that may be
691*4882a593Smuzhiyun  * verity-enabled
692*4882a593Smuzhiyun  * @inode: the inode being opened
693*4882a593Smuzhiyun  * @filp: the struct file being set up
694*4882a593Smuzhiyun  *
695*4882a593Smuzhiyun  * When opening a verity file, set up data_file->df_verity_file_digest if not
696*4882a593Smuzhiyun  * already done. Note that incfs does not allow opening for writing, so there is
697*4882a593Smuzhiyun  * no need for that check.
698*4882a593Smuzhiyun  *
699*4882a593Smuzhiyun  * Return: 0 on success, -errno on failure
700*4882a593Smuzhiyun  */
incfs_fsverity_file_open(struct inode * inode,struct file * filp)701*4882a593Smuzhiyun int incfs_fsverity_file_open(struct inode *inode, struct file *filp)
702*4882a593Smuzhiyun {
703*4882a593Smuzhiyun 	if (IS_VERITY(inode))
704*4882a593Smuzhiyun 		return ensure_verity_info(inode, filp);
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun 	return 0;
707*4882a593Smuzhiyun }
708*4882a593Smuzhiyun 
incfs_ioctl_measure_verity(struct file * filp,void __user * _uarg)709*4882a593Smuzhiyun int incfs_ioctl_measure_verity(struct file *filp, void __user *_uarg)
710*4882a593Smuzhiyun {
711*4882a593Smuzhiyun 	struct inode *inode = file_inode(filp);
712*4882a593Smuzhiyun 	struct mem_range verity_file_digest = incfs_get_verity_digest(inode);
713*4882a593Smuzhiyun 	struct fsverity_digest __user *uarg = _uarg;
714*4882a593Smuzhiyun 	struct fsverity_digest arg;
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun 	if (!verity_file_digest.data || !verity_file_digest.len)
717*4882a593Smuzhiyun 		return -ENODATA; /* not a verity file */
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun 	/*
720*4882a593Smuzhiyun 	 * The user specifies the digest_size their buffer has space for; we can
721*4882a593Smuzhiyun 	 * return the digest if it fits in the available space.  We write back
722*4882a593Smuzhiyun 	 * the actual size, which may be shorter than the user-specified size.
723*4882a593Smuzhiyun 	 */
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun 	if (get_user(arg.digest_size, &uarg->digest_size))
726*4882a593Smuzhiyun 		return -EFAULT;
727*4882a593Smuzhiyun 	if (arg.digest_size < verity_file_digest.len)
728*4882a593Smuzhiyun 		return -EOVERFLOW;
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun 	memset(&arg, 0, sizeof(arg));
731*4882a593Smuzhiyun 	arg.digest_algorithm = FS_VERITY_HASH_ALG_SHA256;
732*4882a593Smuzhiyun 	arg.digest_size = verity_file_digest.len;
733*4882a593Smuzhiyun 
734*4882a593Smuzhiyun 	if (copy_to_user(uarg, &arg, sizeof(arg)))
735*4882a593Smuzhiyun 		return -EFAULT;
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun 	if (copy_to_user(uarg->digest, verity_file_digest.data,
738*4882a593Smuzhiyun 			 verity_file_digest.len))
739*4882a593Smuzhiyun 		return -EFAULT;
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun 	return 0;
742*4882a593Smuzhiyun }
743*4882a593Smuzhiyun 
incfs_read_merkle_tree(struct file * filp,void __user * buf,u64 start_offset,int length)744*4882a593Smuzhiyun static int incfs_read_merkle_tree(struct file *filp, void __user *buf,
745*4882a593Smuzhiyun 				  u64 start_offset, int length)
746*4882a593Smuzhiyun {
747*4882a593Smuzhiyun 	struct mem_range tmp_buf;
748*4882a593Smuzhiyun 	size_t offset;
749*4882a593Smuzhiyun 	int retval = 0;
750*4882a593Smuzhiyun 	int err = 0;
751*4882a593Smuzhiyun 	struct data_file *df = get_incfs_data_file(filp);
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun 	if (!df)
754*4882a593Smuzhiyun 		return -EINVAL;
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun 	tmp_buf = (struct mem_range) {
757*4882a593Smuzhiyun 		.data = kzalloc(INCFS_DATA_FILE_BLOCK_SIZE, GFP_NOFS),
758*4882a593Smuzhiyun 		.len = INCFS_DATA_FILE_BLOCK_SIZE,
759*4882a593Smuzhiyun 	};
760*4882a593Smuzhiyun 	if (!tmp_buf.data)
761*4882a593Smuzhiyun 		return -ENOMEM;
762*4882a593Smuzhiyun 
763*4882a593Smuzhiyun 	for (offset = start_offset; offset < start_offset + length;
764*4882a593Smuzhiyun 	     offset += tmp_buf.len) {
765*4882a593Smuzhiyun 		err = incfs_read_merkle_tree_blocks(tmp_buf, df, offset);
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun 		if (err < 0)
768*4882a593Smuzhiyun 			break;
769*4882a593Smuzhiyun 
770*4882a593Smuzhiyun 		if (err != tmp_buf.len)
771*4882a593Smuzhiyun 			break;
772*4882a593Smuzhiyun 
773*4882a593Smuzhiyun 		if (copy_to_user(buf, tmp_buf.data, tmp_buf.len))
774*4882a593Smuzhiyun 			break;
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun 		buf += tmp_buf.len;
777*4882a593Smuzhiyun 		retval += tmp_buf.len;
778*4882a593Smuzhiyun 	}
779*4882a593Smuzhiyun 
780*4882a593Smuzhiyun 	kfree(tmp_buf.data);
781*4882a593Smuzhiyun 	return retval ? retval : err;
782*4882a593Smuzhiyun }
783*4882a593Smuzhiyun 
incfs_read_descriptor(struct file * filp,void __user * buf,u64 offset,int length)784*4882a593Smuzhiyun static int incfs_read_descriptor(struct file *filp,
785*4882a593Smuzhiyun 				 void __user *buf, u64 offset, int length)
786*4882a593Smuzhiyun {
787*4882a593Smuzhiyun 	int err;
788*4882a593Smuzhiyun 	struct fsverity_descriptor *desc = incfs_get_fsverity_descriptor(filp,
789*4882a593Smuzhiyun 						FS_VERITY_HASH_ALG_SHA256);
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun 	if (IS_ERR(desc))
792*4882a593Smuzhiyun 		return PTR_ERR(desc);
793*4882a593Smuzhiyun 	length = min_t(u64, length, sizeof(*desc));
794*4882a593Smuzhiyun 	err = copy_to_user(buf, desc, length);
795*4882a593Smuzhiyun 	kfree(desc);
796*4882a593Smuzhiyun 	return err ? err : length;
797*4882a593Smuzhiyun }
798*4882a593Smuzhiyun 
incfs_read_signature(struct file * filp,void __user * buf,u64 offset,int length)799*4882a593Smuzhiyun static int incfs_read_signature(struct file *filp,
800*4882a593Smuzhiyun 				void __user *buf, u64 offset, int length)
801*4882a593Smuzhiyun {
802*4882a593Smuzhiyun 	size_t sig_size;
803*4882a593Smuzhiyun 	static u8 *signature;
804*4882a593Smuzhiyun 	int err;
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun 	signature = incfs_get_verity_signature(filp, &sig_size);
807*4882a593Smuzhiyun 	if (IS_ERR(signature))
808*4882a593Smuzhiyun 		return PTR_ERR(signature);
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun 	if (!signature)
811*4882a593Smuzhiyun 		return -ENODATA;
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun 	length = min_t(u64, length, sig_size);
814*4882a593Smuzhiyun 	err = copy_to_user(buf, signature, length);
815*4882a593Smuzhiyun 	kfree(signature);
816*4882a593Smuzhiyun 	return err ? err : length;
817*4882a593Smuzhiyun }
818*4882a593Smuzhiyun 
incfs_ioctl_read_verity_metadata(struct file * filp,const void __user * uarg)819*4882a593Smuzhiyun int incfs_ioctl_read_verity_metadata(struct file *filp,
820*4882a593Smuzhiyun 				     const void __user *uarg)
821*4882a593Smuzhiyun {
822*4882a593Smuzhiyun 	struct fsverity_read_metadata_arg arg;
823*4882a593Smuzhiyun 	int length;
824*4882a593Smuzhiyun 	void __user *buf;
825*4882a593Smuzhiyun 
826*4882a593Smuzhiyun 	if (copy_from_user(&arg, uarg, sizeof(arg)))
827*4882a593Smuzhiyun 		return -EFAULT;
828*4882a593Smuzhiyun 
829*4882a593Smuzhiyun 	if (arg.__reserved)
830*4882a593Smuzhiyun 		return -EINVAL;
831*4882a593Smuzhiyun 
832*4882a593Smuzhiyun 	/* offset + length must not overflow. */
833*4882a593Smuzhiyun 	if (arg.offset + arg.length < arg.offset)
834*4882a593Smuzhiyun 		return -EINVAL;
835*4882a593Smuzhiyun 
836*4882a593Smuzhiyun 	/* Ensure that the return value will fit in INT_MAX. */
837*4882a593Smuzhiyun 	length = min_t(u64, arg.length, INT_MAX);
838*4882a593Smuzhiyun 
839*4882a593Smuzhiyun 	buf = u64_to_user_ptr(arg.buf_ptr);
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun 	switch (arg.metadata_type) {
842*4882a593Smuzhiyun 	case FS_VERITY_METADATA_TYPE_MERKLE_TREE:
843*4882a593Smuzhiyun 		return incfs_read_merkle_tree(filp, buf, arg.offset, length);
844*4882a593Smuzhiyun 	case FS_VERITY_METADATA_TYPE_DESCRIPTOR:
845*4882a593Smuzhiyun 		return incfs_read_descriptor(filp, buf, arg.offset, length);
846*4882a593Smuzhiyun 	case FS_VERITY_METADATA_TYPE_SIGNATURE:
847*4882a593Smuzhiyun 		return incfs_read_signature(filp, buf, arg.offset, length);
848*4882a593Smuzhiyun 	default:
849*4882a593Smuzhiyun 		return -EINVAL;
850*4882a593Smuzhiyun 	}
851*4882a593Smuzhiyun }
852