xref: /openbmc/linux/include/linux/fsverity.h (revision 74836ecb)
1fd2d1acfSEric Biggers /* SPDX-License-Identifier: GPL-2.0 */
2fd2d1acfSEric Biggers /*
3fd2d1acfSEric Biggers  * fs-verity: read-only file-based authenticity protection
4fd2d1acfSEric Biggers  *
5fd2d1acfSEric Biggers  * This header declares the interface between the fs/verity/ support layer and
6fd2d1acfSEric Biggers  * filesystems that support fs-verity.
7fd2d1acfSEric Biggers  *
8fd2d1acfSEric Biggers  * Copyright 2019 Google LLC
9fd2d1acfSEric Biggers  */
10fd2d1acfSEric Biggers 
11fd2d1acfSEric Biggers #ifndef _LINUX_FSVERITY_H
12fd2d1acfSEric Biggers #define _LINUX_FSVERITY_H
13fd2d1acfSEric Biggers 
14fd2d1acfSEric Biggers #include <linux/fs.h>
155d0f0e57SEric Biggers #include <linux/mm.h>
16246d9216SMimi Zohar #include <crypto/hash_info.h>
17246d9216SMimi Zohar #include <crypto/sha2.h>
18fd2d1acfSEric Biggers #include <uapi/linux/fsverity.h>
19fd2d1acfSEric Biggers 
20246d9216SMimi Zohar /*
21246d9216SMimi Zohar  * Largest digest size among all hash algorithms supported by fs-verity.
22246d9216SMimi Zohar  * Currently assumed to be <= size of fsverity_descriptor::root_hash.
23246d9216SMimi Zohar  */
24246d9216SMimi Zohar #define FS_VERITY_MAX_DIGEST_SIZE	SHA512_DIGEST_SIZE
25246d9216SMimi Zohar 
2638622010SBoris Burkov /* Arbitrary limit to bound the kmalloc() size.  Can be changed. */
2738622010SBoris Burkov #define FS_VERITY_MAX_DESCRIPTOR_SIZE	16384
2838622010SBoris Burkov 
29fd2d1acfSEric Biggers /* Verity operations for filesystems */
30fd2d1acfSEric Biggers struct fsverity_operations {
31fd2d1acfSEric Biggers 
32fd2d1acfSEric Biggers 	/**
333fda4c61SEric Biggers 	 * Begin enabling verity on the given file.
343fda4c61SEric Biggers 	 *
353fda4c61SEric Biggers 	 * @filp: a readonly file descriptor for the file
363fda4c61SEric Biggers 	 *
373fda4c61SEric Biggers 	 * The filesystem must do any needed filesystem-specific preparations
383fda4c61SEric Biggers 	 * for enabling verity, e.g. evicting inline data.  It also must return
393fda4c61SEric Biggers 	 * -EBUSY if verity is already being enabled on the given file.
403fda4c61SEric Biggers 	 *
413fda4c61SEric Biggers 	 * i_rwsem is held for write.
423fda4c61SEric Biggers 	 *
433fda4c61SEric Biggers 	 * Return: 0 on success, -errno on failure
443fda4c61SEric Biggers 	 */
453fda4c61SEric Biggers 	int (*begin_enable_verity)(struct file *filp);
463fda4c61SEric Biggers 
473fda4c61SEric Biggers 	/**
483fda4c61SEric Biggers 	 * End enabling verity on the given file.
493fda4c61SEric Biggers 	 *
503fda4c61SEric Biggers 	 * @filp: a readonly file descriptor for the file
513fda4c61SEric Biggers 	 * @desc: the verity descriptor to write, or NULL on failure
523fda4c61SEric Biggers 	 * @desc_size: size of verity descriptor, or 0 on failure
533fda4c61SEric Biggers 	 * @merkle_tree_size: total bytes the Merkle tree took up
543fda4c61SEric Biggers 	 *
553fda4c61SEric Biggers 	 * If desc == NULL, then enabling verity failed and the filesystem only
563fda4c61SEric Biggers 	 * must do any necessary cleanups.  Else, it must also store the given
573fda4c61SEric Biggers 	 * verity descriptor to a fs-specific location associated with the inode
583fda4c61SEric Biggers 	 * and do any fs-specific actions needed to mark the inode as a verity
593fda4c61SEric Biggers 	 * inode, e.g. setting a bit in the on-disk inode.  The filesystem is
603fda4c61SEric Biggers 	 * also responsible for setting the S_VERITY flag in the VFS inode.
613fda4c61SEric Biggers 	 *
623fda4c61SEric Biggers 	 * i_rwsem is held for write, but it may have been dropped between
633fda4c61SEric Biggers 	 * ->begin_enable_verity() and ->end_enable_verity().
643fda4c61SEric Biggers 	 *
653fda4c61SEric Biggers 	 * Return: 0 on success, -errno on failure
663fda4c61SEric Biggers 	 */
673fda4c61SEric Biggers 	int (*end_enable_verity)(struct file *filp, const void *desc,
683fda4c61SEric Biggers 				 size_t desc_size, u64 merkle_tree_size);
693fda4c61SEric Biggers 
703fda4c61SEric Biggers 	/**
71fd2d1acfSEric Biggers 	 * Get the verity descriptor of the given inode.
72fd2d1acfSEric Biggers 	 *
73fd2d1acfSEric Biggers 	 * @inode: an inode with the S_VERITY flag set
74fd2d1acfSEric Biggers 	 * @buf: buffer in which to place the verity descriptor
75fd2d1acfSEric Biggers 	 * @bufsize: size of @buf, or 0 to retrieve the size only
76fd2d1acfSEric Biggers 	 *
77fd2d1acfSEric Biggers 	 * If bufsize == 0, then the size of the verity descriptor is returned.
78fd2d1acfSEric Biggers 	 * Otherwise the verity descriptor is written to 'buf' and its actual
79fd2d1acfSEric Biggers 	 * size is returned; -ERANGE is returned if it's too large.  This may be
80fd2d1acfSEric Biggers 	 * called by multiple processes concurrently on the same inode.
81fd2d1acfSEric Biggers 	 *
82fd2d1acfSEric Biggers 	 * Return: the size on success, -errno on failure
83fd2d1acfSEric Biggers 	 */
84fd2d1acfSEric Biggers 	int (*get_verity_descriptor)(struct inode *inode, void *buf,
85fd2d1acfSEric Biggers 				     size_t bufsize);
868a1d0f9cSEric Biggers 
878a1d0f9cSEric Biggers 	/**
888a1d0f9cSEric Biggers 	 * Read a Merkle tree page of the given inode.
898a1d0f9cSEric Biggers 	 *
908a1d0f9cSEric Biggers 	 * @inode: the inode
918a1d0f9cSEric Biggers 	 * @index: 0-based index of the page within the Merkle tree
92fd39073dSEric Biggers 	 * @num_ra_pages: The number of Merkle tree pages that should be
93fd39073dSEric Biggers 	 *		  prefetched starting at @index if the page at @index
94fd39073dSEric Biggers 	 *		  isn't already cached.  Implementations may ignore this
95fd39073dSEric Biggers 	 *		  argument; it's only a performance optimization.
968a1d0f9cSEric Biggers 	 *
9756124d6cSEric Biggers 	 * This can be called at any time on an open verity file.  It may be
988a1d0f9cSEric Biggers 	 * called by multiple processes concurrently, even with the same page.
998a1d0f9cSEric Biggers 	 *
1008a1d0f9cSEric Biggers 	 * Note that this must retrieve a *page*, not necessarily a *block*.
1018a1d0f9cSEric Biggers 	 *
1028a1d0f9cSEric Biggers 	 * Return: the page on success, ERR_PTR() on failure
1038a1d0f9cSEric Biggers 	 */
1048a1d0f9cSEric Biggers 	struct page *(*read_merkle_tree_page)(struct inode *inode,
105fd39073dSEric Biggers 					      pgoff_t index,
106fd39073dSEric Biggers 					      unsigned long num_ra_pages);
1073fda4c61SEric Biggers 
1083fda4c61SEric Biggers 	/**
1093fda4c61SEric Biggers 	 * Write a Merkle tree block to the given inode.
1103fda4c61SEric Biggers 	 *
1113fda4c61SEric Biggers 	 * @inode: the inode for which the Merkle tree is being built
11272ea15f0SEric Biggers 	 * @buf: the Merkle tree block to write
11372ea15f0SEric Biggers 	 * @pos: the position of the block in the Merkle tree (in bytes)
11472ea15f0SEric Biggers 	 * @size: the Merkle tree block size (in bytes)
1153fda4c61SEric Biggers 	 *
1163fda4c61SEric Biggers 	 * This is only called between ->begin_enable_verity() and
1173fda4c61SEric Biggers 	 * ->end_enable_verity().
1183fda4c61SEric Biggers 	 *
1193fda4c61SEric Biggers 	 * Return: 0 on success, -errno on failure
1203fda4c61SEric Biggers 	 */
1213fda4c61SEric Biggers 	int (*write_merkle_tree_block)(struct inode *inode, const void *buf,
12272ea15f0SEric Biggers 				       u64 pos, unsigned int size);
123fd2d1acfSEric Biggers };
124fd2d1acfSEric Biggers 
125fd2d1acfSEric Biggers #ifdef CONFIG_FS_VERITY
126fd2d1acfSEric Biggers 
fsverity_get_info(const struct inode * inode)127fd2d1acfSEric Biggers static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
128fd2d1acfSEric Biggers {
129f3db0bedSEric Biggers 	/*
130f3db0bedSEric Biggers 	 * Pairs with the cmpxchg_release() in fsverity_set_info().
131f3db0bedSEric Biggers 	 * I.e., another task may publish ->i_verity_info concurrently,
132f3db0bedSEric Biggers 	 * executing a RELEASE barrier.  We need to use smp_load_acquire() here
133f3db0bedSEric Biggers 	 * to safely ACQUIRE the memory the other task published.
134f3db0bedSEric Biggers 	 */
135f3db0bedSEric Biggers 	return smp_load_acquire(&inode->i_verity_info);
136fd2d1acfSEric Biggers }
137fd2d1acfSEric Biggers 
1383fda4c61SEric Biggers /* enable.c */
1393fda4c61SEric Biggers 
1409cd6b593SEric Biggers int fsverity_ioctl_enable(struct file *filp, const void __user *arg);
1413fda4c61SEric Biggers 
1424dd893d8SEric Biggers /* measure.c */
1434dd893d8SEric Biggers 
1449cd6b593SEric Biggers int fsverity_ioctl_measure(struct file *filp, void __user *arg);
145246d9216SMimi Zohar int fsverity_get_digest(struct inode *inode,
146*74836ecbSEric Biggers 			u8 raw_digest[FS_VERITY_MAX_DIGEST_SIZE],
147*74836ecbSEric Biggers 			u8 *alg, enum hash_algo *halg);
1484dd893d8SEric Biggers 
149fd2d1acfSEric Biggers /* open.c */
150fd2d1acfSEric Biggers 
151a6528a96SEric Biggers int __fsverity_file_open(struct inode *inode, struct file *filp);
15201d90c07SEric Biggers int __fsverity_prepare_setattr(struct dentry *dentry, struct iattr *attr);
1539642946cSEric Biggers void __fsverity_cleanup_inode(struct inode *inode);
1549642946cSEric Biggers 
1559642946cSEric Biggers /**
1569642946cSEric Biggers  * fsverity_cleanup_inode() - free the inode's verity info, if present
1579642946cSEric Biggers  * @inode: an inode being evicted
1589642946cSEric Biggers  *
1599642946cSEric Biggers  * Filesystems must call this on inode eviction to free ->i_verity_info.
1609642946cSEric Biggers  */
fsverity_cleanup_inode(struct inode * inode)1619642946cSEric Biggers static inline void fsverity_cleanup_inode(struct inode *inode)
1629642946cSEric Biggers {
1639642946cSEric Biggers 	if (inode->i_verity_info)
1649642946cSEric Biggers 		__fsverity_cleanup_inode(inode);
1659642946cSEric Biggers }
166fd2d1acfSEric Biggers 
167e17fe657SEric Biggers /* read_metadata.c */
168e17fe657SEric Biggers 
169e17fe657SEric Biggers int fsverity_ioctl_read_metadata(struct file *filp, const void __user *uarg);
170e17fe657SEric Biggers 
1718a1d0f9cSEric Biggers /* verify.c */
1728a1d0f9cSEric Biggers 
1735d0f0e57SEric Biggers bool fsverity_verify_blocks(struct folio *folio, size_t len, size_t offset);
1749cd6b593SEric Biggers void fsverity_verify_bio(struct bio *bio);
1759cd6b593SEric Biggers void fsverity_enqueue_verify_work(struct work_struct *work);
1768a1d0f9cSEric Biggers 
177fd2d1acfSEric Biggers #else /* !CONFIG_FS_VERITY */
178fd2d1acfSEric Biggers 
fsverity_get_info(const struct inode * inode)179fd2d1acfSEric Biggers static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
180fd2d1acfSEric Biggers {
181fd2d1acfSEric Biggers 	return NULL;
182fd2d1acfSEric Biggers }
183fd2d1acfSEric Biggers 
1843fda4c61SEric Biggers /* enable.c */
1853fda4c61SEric Biggers 
fsverity_ioctl_enable(struct file * filp,const void __user * arg)1863fda4c61SEric Biggers static inline int fsverity_ioctl_enable(struct file *filp,
1873fda4c61SEric Biggers 					const void __user *arg)
1883fda4c61SEric Biggers {
1893fda4c61SEric Biggers 	return -EOPNOTSUPP;
1903fda4c61SEric Biggers }
1913fda4c61SEric Biggers 
1924dd893d8SEric Biggers /* measure.c */
1934dd893d8SEric Biggers 
fsverity_ioctl_measure(struct file * filp,void __user * arg)1944dd893d8SEric Biggers static inline int fsverity_ioctl_measure(struct file *filp, void __user *arg)
1954dd893d8SEric Biggers {
1964dd893d8SEric Biggers 	return -EOPNOTSUPP;
1974dd893d8SEric Biggers }
1984dd893d8SEric Biggers 
fsverity_get_digest(struct inode * inode,u8 raw_digest[FS_VERITY_MAX_DIGEST_SIZE],u8 * alg,enum hash_algo * halg)199246d9216SMimi Zohar static inline int fsverity_get_digest(struct inode *inode,
200*74836ecbSEric Biggers 				      u8 raw_digest[FS_VERITY_MAX_DIGEST_SIZE],
201*74836ecbSEric Biggers 				      u8 *alg, enum hash_algo *halg)
202246d9216SMimi Zohar {
203*74836ecbSEric Biggers 	/*
204*74836ecbSEric Biggers 	 * fsverity is not enabled in the kernel configuration, so always report
205*74836ecbSEric Biggers 	 * that the file doesn't have fsverity enabled (digest size 0).
206*74836ecbSEric Biggers 	 */
207*74836ecbSEric Biggers 	return 0;
208246d9216SMimi Zohar }
209246d9216SMimi Zohar 
210fd2d1acfSEric Biggers /* open.c */
211fd2d1acfSEric Biggers 
__fsverity_file_open(struct inode * inode,struct file * filp)212a6528a96SEric Biggers static inline int __fsverity_file_open(struct inode *inode, struct file *filp)
213fd2d1acfSEric Biggers {
214a6528a96SEric Biggers 	return -EOPNOTSUPP;
215fd2d1acfSEric Biggers }
216fd2d1acfSEric Biggers 
__fsverity_prepare_setattr(struct dentry * dentry,struct iattr * attr)21701d90c07SEric Biggers static inline int __fsverity_prepare_setattr(struct dentry *dentry,
218c1d9b584SEric Biggers 					     struct iattr *attr)
219c1d9b584SEric Biggers {
22001d90c07SEric Biggers 	return -EOPNOTSUPP;
221c1d9b584SEric Biggers }
222c1d9b584SEric Biggers 
fsverity_cleanup_inode(struct inode * inode)223fd2d1acfSEric Biggers static inline void fsverity_cleanup_inode(struct inode *inode)
224fd2d1acfSEric Biggers {
225fd2d1acfSEric Biggers }
226fd2d1acfSEric Biggers 
227e17fe657SEric Biggers /* read_metadata.c */
228e17fe657SEric Biggers 
fsverity_ioctl_read_metadata(struct file * filp,const void __user * uarg)229e17fe657SEric Biggers static inline int fsverity_ioctl_read_metadata(struct file *filp,
230e17fe657SEric Biggers 					       const void __user *uarg)
231e17fe657SEric Biggers {
232e17fe657SEric Biggers 	return -EOPNOTSUPP;
233e17fe657SEric Biggers }
234e17fe657SEric Biggers 
2358a1d0f9cSEric Biggers /* verify.c */
2368a1d0f9cSEric Biggers 
fsverity_verify_blocks(struct folio * folio,size_t len,size_t offset)2375d0f0e57SEric Biggers static inline bool fsverity_verify_blocks(struct folio *folio, size_t len,
2385d0f0e57SEric Biggers 					  size_t offset)
2398a1d0f9cSEric Biggers {
2408eb8af4bSEric Biggers 	WARN_ON_ONCE(1);
2418a1d0f9cSEric Biggers 	return false;
2428a1d0f9cSEric Biggers }
2438a1d0f9cSEric Biggers 
fsverity_verify_bio(struct bio * bio)2448a1d0f9cSEric Biggers static inline void fsverity_verify_bio(struct bio *bio)
2458a1d0f9cSEric Biggers {
2468eb8af4bSEric Biggers 	WARN_ON_ONCE(1);
2478a1d0f9cSEric Biggers }
2488a1d0f9cSEric Biggers 
fsverity_enqueue_verify_work(struct work_struct * work)2498a1d0f9cSEric Biggers static inline void fsverity_enqueue_verify_work(struct work_struct *work)
2508a1d0f9cSEric Biggers {
2518eb8af4bSEric Biggers 	WARN_ON_ONCE(1);
2528a1d0f9cSEric Biggers }
2538a1d0f9cSEric Biggers 
254fd2d1acfSEric Biggers #endif	/* !CONFIG_FS_VERITY */
255fd2d1acfSEric Biggers 
fsverity_verify_folio(struct folio * folio)2565d0f0e57SEric Biggers static inline bool fsverity_verify_folio(struct folio *folio)
2575d0f0e57SEric Biggers {
2585d0f0e57SEric Biggers 	return fsverity_verify_blocks(folio, folio_size(folio), 0);
2595d0f0e57SEric Biggers }
2605d0f0e57SEric Biggers 
fsverity_verify_page(struct page * page)2615306892aSEric Biggers static inline bool fsverity_verify_page(struct page *page)
2625306892aSEric Biggers {
2635d0f0e57SEric Biggers 	return fsverity_verify_blocks(page_folio(page), PAGE_SIZE, 0);
2645306892aSEric Biggers }
2655306892aSEric Biggers 
2668a1d0f9cSEric Biggers /**
2678a1d0f9cSEric Biggers  * fsverity_active() - do reads from the inode need to go through fs-verity?
2686377a38bSEric Biggers  * @inode: inode to check
2698a1d0f9cSEric Biggers  *
2708a1d0f9cSEric Biggers  * This checks whether ->i_verity_info has been set.
2718a1d0f9cSEric Biggers  *
272704528d8SMatthew Wilcox (Oracle)  * Filesystems call this from ->readahead() to check whether the pages need to
2738a1d0f9cSEric Biggers  * be verified or not.  Don't use IS_VERITY() for this purpose; it's subject to
2748a1d0f9cSEric Biggers  * a race condition where the file is being read concurrently with
2758a1d0f9cSEric Biggers  * FS_IOC_ENABLE_VERITY completing.  (S_VERITY is set before ->i_verity_info.)
2766377a38bSEric Biggers  *
2776377a38bSEric Biggers  * Return: true if reads need to go through fs-verity, otherwise false
2788a1d0f9cSEric Biggers  */
fsverity_active(const struct inode * inode)2798a1d0f9cSEric Biggers static inline bool fsverity_active(const struct inode *inode)
2808a1d0f9cSEric Biggers {
2818a1d0f9cSEric Biggers 	return fsverity_get_info(inode) != NULL;
2828a1d0f9cSEric Biggers }
2838a1d0f9cSEric Biggers 
284a6528a96SEric Biggers /**
285a6528a96SEric Biggers  * fsverity_file_open() - prepare to open a verity file
286a6528a96SEric Biggers  * @inode: the inode being opened
287a6528a96SEric Biggers  * @filp: the struct file being set up
288a6528a96SEric Biggers  *
289a6528a96SEric Biggers  * When opening a verity file, deny the open if it is for writing.  Otherwise,
290a6528a96SEric Biggers  * set up the inode's ->i_verity_info if not already done.
291a6528a96SEric Biggers  *
292a6528a96SEric Biggers  * When combined with fscrypt, this must be called after fscrypt_file_open().
293a6528a96SEric Biggers  * Otherwise, we won't have the key set up to decrypt the verity metadata.
294a6528a96SEric Biggers  *
295a6528a96SEric Biggers  * Return: 0 on success, -errno on failure
296a6528a96SEric Biggers  */
fsverity_file_open(struct inode * inode,struct file * filp)297a6528a96SEric Biggers static inline int fsverity_file_open(struct inode *inode, struct file *filp)
298a6528a96SEric Biggers {
299a6528a96SEric Biggers 	if (IS_VERITY(inode))
300a6528a96SEric Biggers 		return __fsverity_file_open(inode, filp);
301a6528a96SEric Biggers 	return 0;
302a6528a96SEric Biggers }
303a6528a96SEric Biggers 
30401d90c07SEric Biggers /**
30501d90c07SEric Biggers  * fsverity_prepare_setattr() - prepare to change a verity inode's attributes
30601d90c07SEric Biggers  * @dentry: dentry through which the inode is being changed
30701d90c07SEric Biggers  * @attr: attributes to change
30801d90c07SEric Biggers  *
30901d90c07SEric Biggers  * Verity files are immutable, so deny truncates.  This isn't covered by the
31001d90c07SEric Biggers  * open-time check because sys_truncate() takes a path, not a file descriptor.
31101d90c07SEric Biggers  *
31201d90c07SEric Biggers  * Return: 0 on success, -errno on failure
31301d90c07SEric Biggers  */
fsverity_prepare_setattr(struct dentry * dentry,struct iattr * attr)31401d90c07SEric Biggers static inline int fsverity_prepare_setattr(struct dentry *dentry,
31501d90c07SEric Biggers 					   struct iattr *attr)
31601d90c07SEric Biggers {
31701d90c07SEric Biggers 	if (IS_VERITY(d_inode(dentry)))
31801d90c07SEric Biggers 		return __fsverity_prepare_setattr(dentry, attr);
31901d90c07SEric Biggers 	return 0;
32001d90c07SEric Biggers }
32101d90c07SEric Biggers 
322fd2d1acfSEric Biggers #endif	/* _LINUX_FSVERITY_H */
323