fs-verity: implement FS_IOC_MEASURE_VERITY ioctl
Add a function for filesystems to call to implement the FS_IOC_MEASURE_VERITY ioctl. This ioctl retrieves the file measurement that fs-verity calculated for the given file and is enforcing for reads; i.e., reads that don't match this hash will fail. This ioctl can be used for authentication or logging of file measurements in userspace. See the "FS_IOC_MEASURE_VERITY" section of Documentation/filesystems/fsverity.rst for the documentation. Reviewed-by: Theodore Ts'o <tytso@mit.edu> Reviewed-by: Jaegeuk Kim <jaegeuk@kernel.org> Signed-off-by: Eric Biggers <ebiggers@google.com>
This commit is contained in:
parent
43005f9bdb
commit
ebeb654881
3 changed files with 69 additions and 0 deletions
|
@ -3,5 +3,6 @@
|
|||
obj-$(CONFIG_FS_VERITY) += enable.o \
|
||||
hash_algs.o \
|
||||
init.o \
|
||||
measure.o \
|
||||
open.o \
|
||||
verify.o
|
||||
|
|
57
fs/verity/measure.c
Normal file
57
fs/verity/measure.c
Normal file
|
@ -0,0 +1,57 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* fs/verity/measure.c: ioctl to get a verity file's measurement
|
||||
*
|
||||
* Copyright 2019 Google LLC
|
||||
*/
|
||||
|
||||
#include "fsverity_private.h"
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
/**
|
||||
* fsverity_ioctl_measure() - get a verity file's measurement
|
||||
*
|
||||
* Retrieve the file measurement that the kernel is enforcing for reads from a
|
||||
* verity file. See the "FS_IOC_MEASURE_VERITY" section of
|
||||
* Documentation/filesystems/fsverity.rst for the documentation.
|
||||
*
|
||||
* Return: 0 on success, -errno on failure
|
||||
*/
|
||||
int fsverity_ioctl_measure(struct file *filp, void __user *_uarg)
|
||||
{
|
||||
const struct inode *inode = file_inode(filp);
|
||||
struct fsverity_digest __user *uarg = _uarg;
|
||||
const struct fsverity_info *vi;
|
||||
const struct fsverity_hash_alg *hash_alg;
|
||||
struct fsverity_digest arg;
|
||||
|
||||
vi = fsverity_get_info(inode);
|
||||
if (!vi)
|
||||
return -ENODATA; /* not a verity file */
|
||||
hash_alg = vi->tree_params.hash_alg;
|
||||
|
||||
/*
|
||||
* The user specifies the digest_size their buffer has space for; we can
|
||||
* return the digest if it fits in the available space. We write back
|
||||
* the actual size, which may be shorter than the user-specified size.
|
||||
*/
|
||||
|
||||
if (get_user(arg.digest_size, &uarg->digest_size))
|
||||
return -EFAULT;
|
||||
if (arg.digest_size < hash_alg->digest_size)
|
||||
return -EOVERFLOW;
|
||||
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
arg.digest_algorithm = hash_alg - fsverity_hash_algs;
|
||||
arg.digest_size = hash_alg->digest_size;
|
||||
|
||||
if (copy_to_user(uarg, &arg, sizeof(arg)))
|
||||
return -EFAULT;
|
||||
|
||||
if (copy_to_user(uarg->digest, vi->measurement, hash_alg->digest_size))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fsverity_ioctl_measure);
|
|
@ -118,6 +118,10 @@ static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
|
|||
|
||||
extern int fsverity_ioctl_enable(struct file *filp, const void __user *arg);
|
||||
|
||||
/* measure.c */
|
||||
|
||||
extern int fsverity_ioctl_measure(struct file *filp, void __user *arg);
|
||||
|
||||
/* open.c */
|
||||
|
||||
extern int fsverity_file_open(struct inode *inode, struct file *filp);
|
||||
|
@ -145,6 +149,13 @@ static inline int fsverity_ioctl_enable(struct file *filp,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* measure.c */
|
||||
|
||||
static inline int fsverity_ioctl_measure(struct file *filp, void __user *arg)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* open.c */
|
||||
|
||||
static inline int fsverity_file_open(struct inode *inode, struct file *filp)
|
||||
|
|
Loading…
Reference in a new issue