Skip to content

Commit

Permalink
fs-verity: implement FS_IOC_MEASURE_VERITY ioctl
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Eric Biggers committed Aug 13, 2019
1 parent 3fda4c6 commit 4dd893d
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 0 deletions.
1 change: 1 addition & 0 deletions fs/verity/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
obj-$(CONFIG_FS_VERITY) += enable.o \
hash_algs.o \
init.o \
measure.o \
open.o \
verify.o
57 changes: 57 additions & 0 deletions fs/verity/measure.c
Original file line number Diff line number Diff line change
@@ -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);
11 changes: 11 additions & 0 deletions include/linux/fsverity.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 4dd893d

Please sign in to comment.