Add the fs-verity shared code in fs/verity/, along with supporting fields in struct inode and struct super_block. Filesystems can hook into this library to implement efficient file-level integrity and/or authenticity for read-only files. It works by implementing the dm-verity mechanism at a file-granular level, using a Merkle tree to verify any block in the file in log(file size) time. fs-verity is a major new VFS feature that will take some time to get right. This prototype may be incompatible with the version that eventually gets upstreamed. If you would like to participate in the design and implementation, please do so on the linux-fscrypt mailing list [1]. Note that this will be a topic of discussion at LSF/MM 2018. The Merkle tree is stored in-line with the file contents, starting at the block past the original i_size. A footer is stored after the Merkle tree describing the original i_size, properties of the Merkle tree, and other information. The metadata is generated using a userspace tool; then, an ioctl tells the kernel to enable fs-verity. The metadata is not stored in an xattr because the Merkle tree may be much larger than XATTR_SIZE_MAX, and in the case of fs-verity combined with fscrypt it's desirable for the metadata to be encrypted to avoid leaking plaintext hashes. In this prototype, an ioctl FS_IOC_SET_VERITY_MEASUREMENT tells the kernel which measurement (hash of root hash + fs-verity footer) to expect for a given inode, pinning it into memory. Future work will replace or supplement this with support for signature verification. The i_size in the in-memory VFS inode is overridden so that userspace only sees the original data, not the fs-verity metadata. However, the i_size stored on-disk remains the full i_size. [1] http://vger.kernel.org/vger-lists.html#linux-fscrypt Co-developed-by: Michael Halcrow <mhalcrow@google.com> Signed-off-by: Michael Halcrow <mhalcrow@google.com> Signed-off-by: Eric Biggers <ebiggers@google.com> (Backported to bluecross. Tested full series with 'android-xfstests -c f2fs -g verity') Conflicts: fs/inode.c include/linux/fs.h Bug: 30972906 Bug: 67380979 Change-Id: Idab791615fe06f4f64496f94b01edbc74f4849c4
93 lines
2.2 KiB
C
93 lines
2.2 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* fs-verity: read-only file-based integrity/authenticity
|
|
*
|
|
* Copyright (C) 2018, Google, Inc.
|
|
*
|
|
* Written by Jaegeuk Kim, Michael Halcrow, and Eric Biggers.
|
|
*/
|
|
|
|
#ifndef _LINUX_FSVERITY_H
|
|
#define _LINUX_FSVERITY_H
|
|
|
|
#include <linux/fs.h>
|
|
|
|
/*
|
|
* fs-verity operations for filesystems
|
|
*/
|
|
struct fsverity_operations {
|
|
bool (*is_verity)(struct inode *inode);
|
|
int (*set_verity)(struct inode *inode);
|
|
struct page *(*read_metadata_page)(struct inode *inode, pgoff_t index);
|
|
};
|
|
|
|
#if __FS_HAS_VERITY
|
|
extern int fsverity_file_open(struct inode *inode, struct file *filp);
|
|
extern int fsverity_prepare_setattr(struct dentry *dentry, struct iattr *attr);
|
|
extern int fsverity_prepare_getattr(struct inode *inode);
|
|
extern void fsverity_cleanup_inode(struct inode *inode);
|
|
extern bool fsverity_verify_page(struct page *page);
|
|
extern void fsverity_verify_bio(struct bio *bio);
|
|
extern void fsverity_enqueue_verify_work(struct work_struct *work);
|
|
extern loff_t fsverity_full_isize(struct inode *inode);
|
|
extern int fsverity_ioctl_set_measurement(struct file *filp,
|
|
const void __user *arg);
|
|
extern int fsverity_ioctl_enable(struct file *filp, const void __user *arg);
|
|
#else
|
|
static inline int fsverity_file_open(struct inode *inode, struct file *filp)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int fsverity_prepare_setattr(struct dentry *dentry,
|
|
struct iattr *attr)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int fsverity_prepare_getattr(struct inode *inode)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline void fsverity_cleanup_inode(struct inode *inode)
|
|
{
|
|
}
|
|
|
|
static inline bool fsverity_verify_page(struct page *page)
|
|
{
|
|
WARN_ON(1);
|
|
return false;
|
|
}
|
|
|
|
static inline void fsverity_verify_bio(struct bio *bio)
|
|
{
|
|
WARN_ON(1);
|
|
}
|
|
|
|
static inline void fsverity_enqueue_verify_work(struct work_struct *work)
|
|
{
|
|
WARN_ON(1);
|
|
}
|
|
|
|
static inline loff_t fsverity_full_isize(struct inode *inode)
|
|
{
|
|
return i_size_read(inode);
|
|
}
|
|
|
|
static inline int fsverity_ioctl_set_measurement(struct file *filp,
|
|
const void __user *arg)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int fsverity_ioctl_enable(struct file *filp,
|
|
const void __user *arg)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
#endif /* !__FS_HAS_VERITY */
|
|
|
|
#endif /* _LINUX_FSVERITY_H */
|