Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Ioctl to get a verity file's digest
0004  *
0005  * Copyright 2019 Google LLC
0006  */
0007 
0008 #include "fsverity_private.h"
0009 
0010 #include <linux/uaccess.h>
0011 
0012 /**
0013  * fsverity_ioctl_measure() - get a verity file's digest
0014  * @filp: file to get digest of
0015  * @_uarg: user pointer to fsverity_digest
0016  *
0017  * Retrieve the file digest that the kernel is enforcing for reads from a verity
0018  * file.  See the "FS_IOC_MEASURE_VERITY" section of
0019  * Documentation/filesystems/fsverity.rst for the documentation.
0020  *
0021  * Return: 0 on success, -errno on failure
0022  */
0023 int fsverity_ioctl_measure(struct file *filp, void __user *_uarg)
0024 {
0025     const struct inode *inode = file_inode(filp);
0026     struct fsverity_digest __user *uarg = _uarg;
0027     const struct fsverity_info *vi;
0028     const struct fsverity_hash_alg *hash_alg;
0029     struct fsverity_digest arg;
0030 
0031     vi = fsverity_get_info(inode);
0032     if (!vi)
0033         return -ENODATA; /* not a verity file */
0034     hash_alg = vi->tree_params.hash_alg;
0035 
0036     /*
0037      * The user specifies the digest_size their buffer has space for; we can
0038      * return the digest if it fits in the available space.  We write back
0039      * the actual size, which may be shorter than the user-specified size.
0040      */
0041 
0042     if (get_user(arg.digest_size, &uarg->digest_size))
0043         return -EFAULT;
0044     if (arg.digest_size < hash_alg->digest_size)
0045         return -EOVERFLOW;
0046 
0047     memset(&arg, 0, sizeof(arg));
0048     arg.digest_algorithm = hash_alg - fsverity_hash_algs;
0049     arg.digest_size = hash_alg->digest_size;
0050 
0051     if (copy_to_user(uarg, &arg, sizeof(arg)))
0052         return -EFAULT;
0053 
0054     if (copy_to_user(uarg->digest, vi->file_digest, hash_alg->digest_size))
0055         return -EFAULT;
0056 
0057     return 0;
0058 }
0059 EXPORT_SYMBOL_GPL(fsverity_ioctl_measure);
0060 
0061 /**
0062  * fsverity_get_digest() - get a verity file's digest
0063  * @inode: inode to get digest of
0064  * @digest: (out) pointer to the digest
0065  * @alg: (out) pointer to the hash algorithm enumeration
0066  *
0067  * Return the file hash algorithm and digest of an fsverity protected file.
0068  * Assumption: before calling fsverity_get_digest(), the file must have been
0069  * opened.
0070  *
0071  * Return: 0 on success, -errno on failure
0072  */
0073 int fsverity_get_digest(struct inode *inode,
0074             u8 digest[FS_VERITY_MAX_DIGEST_SIZE],
0075             enum hash_algo *alg)
0076 {
0077     const struct fsverity_info *vi;
0078     const struct fsverity_hash_alg *hash_alg;
0079     int i;
0080 
0081     vi = fsverity_get_info(inode);
0082     if (!vi)
0083         return -ENODATA; /* not a verity file */
0084 
0085     hash_alg = vi->tree_params.hash_alg;
0086     memset(digest, 0, FS_VERITY_MAX_DIGEST_SIZE);
0087 
0088     /* convert the verity hash algorithm name to a hash_algo_name enum */
0089     i = match_string(hash_algo_name, HASH_ALGO__LAST, hash_alg->name);
0090     if (i < 0)
0091         return -EINVAL;
0092     *alg = i;
0093 
0094     if (WARN_ON_ONCE(hash_alg->digest_size != hash_digest_size[*alg]))
0095         return -EINVAL;
0096     memcpy(digest, vi->file_digest, hash_alg->digest_size);
0097 
0098     pr_debug("file digest %s:%*phN\n", hash_algo_name[*alg],
0099          hash_digest_size[*alg], digest);
0100 
0101     return 0;
0102 }