Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Opening fs-verity files
0004  *
0005  * Copyright 2019 Google LLC
0006  */
0007 
0008 #include "fsverity_private.h"
0009 
0010 #include <linux/slab.h>
0011 
0012 static struct kmem_cache *fsverity_info_cachep;
0013 
0014 /**
0015  * fsverity_init_merkle_tree_params() - initialize Merkle tree parameters
0016  * @params: the parameters struct to initialize
0017  * @inode: the inode for which the Merkle tree is being built
0018  * @hash_algorithm: number of hash algorithm to use
0019  * @log_blocksize: log base 2 of block size to use
0020  * @salt: pointer to salt (optional)
0021  * @salt_size: size of salt, possibly 0
0022  *
0023  * Validate the hash algorithm and block size, then compute the tree topology
0024  * (num levels, num blocks in each level, etc.) and initialize @params.
0025  *
0026  * Return: 0 on success, -errno on failure
0027  */
0028 int fsverity_init_merkle_tree_params(struct merkle_tree_params *params,
0029                      const struct inode *inode,
0030                      unsigned int hash_algorithm,
0031                      unsigned int log_blocksize,
0032                      const u8 *salt, size_t salt_size)
0033 {
0034     struct fsverity_hash_alg *hash_alg;
0035     int err;
0036     u64 blocks;
0037     u64 offset;
0038     int level;
0039 
0040     memset(params, 0, sizeof(*params));
0041 
0042     hash_alg = fsverity_get_hash_alg(inode, hash_algorithm);
0043     if (IS_ERR(hash_alg))
0044         return PTR_ERR(hash_alg);
0045     params->hash_alg = hash_alg;
0046     params->digest_size = hash_alg->digest_size;
0047 
0048     params->hashstate = fsverity_prepare_hash_state(hash_alg, salt,
0049                             salt_size);
0050     if (IS_ERR(params->hashstate)) {
0051         err = PTR_ERR(params->hashstate);
0052         params->hashstate = NULL;
0053         fsverity_err(inode, "Error %d preparing hash state", err);
0054         goto out_err;
0055     }
0056 
0057     if (log_blocksize != PAGE_SHIFT) {
0058         fsverity_warn(inode, "Unsupported log_blocksize: %u",
0059                   log_blocksize);
0060         err = -EINVAL;
0061         goto out_err;
0062     }
0063     params->log_blocksize = log_blocksize;
0064     params->block_size = 1 << log_blocksize;
0065 
0066     if (WARN_ON(!is_power_of_2(params->digest_size))) {
0067         err = -EINVAL;
0068         goto out_err;
0069     }
0070     if (params->block_size < 2 * params->digest_size) {
0071         fsverity_warn(inode,
0072                   "Merkle tree block size (%u) too small for hash algorithm \"%s\"",
0073                   params->block_size, hash_alg->name);
0074         err = -EINVAL;
0075         goto out_err;
0076     }
0077     params->log_arity = params->log_blocksize - ilog2(params->digest_size);
0078     params->hashes_per_block = 1 << params->log_arity;
0079 
0080     pr_debug("Merkle tree uses %s with %u-byte blocks (%u hashes/block), salt=%*phN\n",
0081          hash_alg->name, params->block_size, params->hashes_per_block,
0082          (int)salt_size, salt);
0083 
0084     /*
0085      * Compute the number of levels in the Merkle tree and create a map from
0086      * level to the starting block of that level.  Level 'num_levels - 1' is
0087      * the root and is stored first.  Level 0 is the level directly "above"
0088      * the data blocks and is stored last.
0089      */
0090 
0091     /* Compute number of levels and the number of blocks in each level */
0092     blocks = ((u64)inode->i_size + params->block_size - 1) >> log_blocksize;
0093     pr_debug("Data is %lld bytes (%llu blocks)\n", inode->i_size, blocks);
0094     while (blocks > 1) {
0095         if (params->num_levels >= FS_VERITY_MAX_LEVELS) {
0096             fsverity_err(inode, "Too many levels in Merkle tree");
0097             err = -EINVAL;
0098             goto out_err;
0099         }
0100         blocks = (blocks + params->hashes_per_block - 1) >>
0101              params->log_arity;
0102         /* temporarily using level_start[] to store blocks in level */
0103         params->level_start[params->num_levels++] = blocks;
0104     }
0105     params->level0_blocks = params->level_start[0];
0106 
0107     /* Compute the starting block of each level */
0108     offset = 0;
0109     for (level = (int)params->num_levels - 1; level >= 0; level--) {
0110         blocks = params->level_start[level];
0111         params->level_start[level] = offset;
0112         pr_debug("Level %d is %llu blocks starting at index %llu\n",
0113              level, blocks, offset);
0114         offset += blocks;
0115     }
0116 
0117     params->tree_size = offset << log_blocksize;
0118     return 0;
0119 
0120 out_err:
0121     kfree(params->hashstate);
0122     memset(params, 0, sizeof(*params));
0123     return err;
0124 }
0125 
0126 /*
0127  * Compute the file digest by hashing the fsverity_descriptor excluding the
0128  * signature and with the sig_size field set to 0.
0129  */
0130 static int compute_file_digest(struct fsverity_hash_alg *hash_alg,
0131                    struct fsverity_descriptor *desc,
0132                    u8 *file_digest)
0133 {
0134     __le32 sig_size = desc->sig_size;
0135     int err;
0136 
0137     desc->sig_size = 0;
0138     err = fsverity_hash_buffer(hash_alg, desc, sizeof(*desc), file_digest);
0139     desc->sig_size = sig_size;
0140 
0141     return err;
0142 }
0143 
0144 /*
0145  * Create a new fsverity_info from the given fsverity_descriptor (with optional
0146  * appended signature), and check the signature if present.  The
0147  * fsverity_descriptor must have already undergone basic validation.
0148  */
0149 struct fsverity_info *fsverity_create_info(const struct inode *inode,
0150                        struct fsverity_descriptor *desc)
0151 {
0152     struct fsverity_info *vi;
0153     int err;
0154 
0155     vi = kmem_cache_zalloc(fsverity_info_cachep, GFP_KERNEL);
0156     if (!vi)
0157         return ERR_PTR(-ENOMEM);
0158     vi->inode = inode;
0159 
0160     err = fsverity_init_merkle_tree_params(&vi->tree_params, inode,
0161                            desc->hash_algorithm,
0162                            desc->log_blocksize,
0163                            desc->salt, desc->salt_size);
0164     if (err) {
0165         fsverity_err(inode,
0166                  "Error %d initializing Merkle tree parameters",
0167                  err);
0168         goto out;
0169     }
0170 
0171     memcpy(vi->root_hash, desc->root_hash, vi->tree_params.digest_size);
0172 
0173     err = compute_file_digest(vi->tree_params.hash_alg, desc,
0174                   vi->file_digest);
0175     if (err) {
0176         fsverity_err(inode, "Error %d computing file digest", err);
0177         goto out;
0178     }
0179     pr_debug("Computed file digest: %s:%*phN\n",
0180          vi->tree_params.hash_alg->name,
0181          vi->tree_params.digest_size, vi->file_digest);
0182 
0183     err = fsverity_verify_signature(vi, desc->signature,
0184                     le32_to_cpu(desc->sig_size));
0185 out:
0186     if (err) {
0187         fsverity_free_info(vi);
0188         vi = ERR_PTR(err);
0189     }
0190     return vi;
0191 }
0192 
0193 void fsverity_set_info(struct inode *inode, struct fsverity_info *vi)
0194 {
0195     /*
0196      * Multiple tasks may race to set ->i_verity_info, so use
0197      * cmpxchg_release().  This pairs with the smp_load_acquire() in
0198      * fsverity_get_info().  I.e., here we publish ->i_verity_info with a
0199      * RELEASE barrier so that other tasks can ACQUIRE it.
0200      */
0201     if (cmpxchg_release(&inode->i_verity_info, NULL, vi) != NULL) {
0202         /* Lost the race, so free the fsverity_info we allocated. */
0203         fsverity_free_info(vi);
0204         /*
0205          * Afterwards, the caller may access ->i_verity_info directly,
0206          * so make sure to ACQUIRE the winning fsverity_info.
0207          */
0208         (void)fsverity_get_info(inode);
0209     }
0210 }
0211 
0212 void fsverity_free_info(struct fsverity_info *vi)
0213 {
0214     if (!vi)
0215         return;
0216     kfree(vi->tree_params.hashstate);
0217     kmem_cache_free(fsverity_info_cachep, vi);
0218 }
0219 
0220 static bool validate_fsverity_descriptor(struct inode *inode,
0221                      const struct fsverity_descriptor *desc,
0222                      size_t desc_size)
0223 {
0224     if (desc_size < sizeof(*desc)) {
0225         fsverity_err(inode, "Unrecognized descriptor size: %zu bytes",
0226                  desc_size);
0227         return false;
0228     }
0229 
0230     if (desc->version != 1) {
0231         fsverity_err(inode, "Unrecognized descriptor version: %u",
0232                  desc->version);
0233         return false;
0234     }
0235 
0236     if (memchr_inv(desc->__reserved, 0, sizeof(desc->__reserved))) {
0237         fsverity_err(inode, "Reserved bits set in descriptor");
0238         return false;
0239     }
0240 
0241     if (desc->salt_size > sizeof(desc->salt)) {
0242         fsverity_err(inode, "Invalid salt_size: %u", desc->salt_size);
0243         return false;
0244     }
0245 
0246     if (le64_to_cpu(desc->data_size) != inode->i_size) {
0247         fsverity_err(inode,
0248                  "Wrong data_size: %llu (desc) != %lld (inode)",
0249                  le64_to_cpu(desc->data_size), inode->i_size);
0250         return false;
0251     }
0252 
0253     if (le32_to_cpu(desc->sig_size) > desc_size - sizeof(*desc)) {
0254         fsverity_err(inode, "Signature overflows verity descriptor");
0255         return false;
0256     }
0257 
0258     return true;
0259 }
0260 
0261 /*
0262  * Read the inode's fsverity_descriptor (with optional appended signature) from
0263  * the filesystem, and do basic validation of it.
0264  */
0265 int fsverity_get_descriptor(struct inode *inode,
0266                 struct fsverity_descriptor **desc_ret)
0267 {
0268     int res;
0269     struct fsverity_descriptor *desc;
0270 
0271     res = inode->i_sb->s_vop->get_verity_descriptor(inode, NULL, 0);
0272     if (res < 0) {
0273         fsverity_err(inode,
0274                  "Error %d getting verity descriptor size", res);
0275         return res;
0276     }
0277     if (res > FS_VERITY_MAX_DESCRIPTOR_SIZE) {
0278         fsverity_err(inode, "Verity descriptor is too large (%d bytes)",
0279                  res);
0280         return -EMSGSIZE;
0281     }
0282     desc = kmalloc(res, GFP_KERNEL);
0283     if (!desc)
0284         return -ENOMEM;
0285     res = inode->i_sb->s_vop->get_verity_descriptor(inode, desc, res);
0286     if (res < 0) {
0287         fsverity_err(inode, "Error %d reading verity descriptor", res);
0288         kfree(desc);
0289         return res;
0290     }
0291 
0292     if (!validate_fsverity_descriptor(inode, desc, res)) {
0293         kfree(desc);
0294         return -EINVAL;
0295     }
0296 
0297     *desc_ret = desc;
0298     return 0;
0299 }
0300 
0301 /* Ensure the inode has an ->i_verity_info */
0302 static int ensure_verity_info(struct inode *inode)
0303 {
0304     struct fsverity_info *vi = fsverity_get_info(inode);
0305     struct fsverity_descriptor *desc;
0306     int err;
0307 
0308     if (vi)
0309         return 0;
0310 
0311     err = fsverity_get_descriptor(inode, &desc);
0312     if (err)
0313         return err;
0314 
0315     vi = fsverity_create_info(inode, desc);
0316     if (IS_ERR(vi)) {
0317         err = PTR_ERR(vi);
0318         goto out_free_desc;
0319     }
0320 
0321     fsverity_set_info(inode, vi);
0322     err = 0;
0323 out_free_desc:
0324     kfree(desc);
0325     return err;
0326 }
0327 
0328 /**
0329  * fsverity_file_open() - prepare to open a verity file
0330  * @inode: the inode being opened
0331  * @filp: the struct file being set up
0332  *
0333  * When opening a verity file, deny the open if it is for writing.  Otherwise,
0334  * set up the inode's ->i_verity_info if not already done.
0335  *
0336  * When combined with fscrypt, this must be called after fscrypt_file_open().
0337  * Otherwise, we won't have the key set up to decrypt the verity metadata.
0338  *
0339  * Return: 0 on success, -errno on failure
0340  */
0341 int fsverity_file_open(struct inode *inode, struct file *filp)
0342 {
0343     if (!IS_VERITY(inode))
0344         return 0;
0345 
0346     if (filp->f_mode & FMODE_WRITE) {
0347         pr_debug("Denying opening verity file (ino %lu) for write\n",
0348              inode->i_ino);
0349         return -EPERM;
0350     }
0351 
0352     return ensure_verity_info(inode);
0353 }
0354 EXPORT_SYMBOL_GPL(fsverity_file_open);
0355 
0356 /**
0357  * fsverity_prepare_setattr() - prepare to change a verity inode's attributes
0358  * @dentry: dentry through which the inode is being changed
0359  * @attr: attributes to change
0360  *
0361  * Verity files are immutable, so deny truncates.  This isn't covered by the
0362  * open-time check because sys_truncate() takes a path, not a file descriptor.
0363  *
0364  * Return: 0 on success, -errno on failure
0365  */
0366 int fsverity_prepare_setattr(struct dentry *dentry, struct iattr *attr)
0367 {
0368     if (IS_VERITY(d_inode(dentry)) && (attr->ia_valid & ATTR_SIZE)) {
0369         pr_debug("Denying truncate of verity file (ino %lu)\n",
0370              d_inode(dentry)->i_ino);
0371         return -EPERM;
0372     }
0373     return 0;
0374 }
0375 EXPORT_SYMBOL_GPL(fsverity_prepare_setattr);
0376 
0377 /**
0378  * fsverity_cleanup_inode() - free the inode's verity info, if present
0379  * @inode: an inode being evicted
0380  *
0381  * Filesystems must call this on inode eviction to free ->i_verity_info.
0382  */
0383 void fsverity_cleanup_inode(struct inode *inode)
0384 {
0385     fsverity_free_info(inode->i_verity_info);
0386     inode->i_verity_info = NULL;
0387 }
0388 EXPORT_SYMBOL_GPL(fsverity_cleanup_inode);
0389 
0390 int __init fsverity_init_info_cache(void)
0391 {
0392     fsverity_info_cachep = KMEM_CACHE_USERCOPY(fsverity_info,
0393                            SLAB_RECLAIM_ACCOUNT,
0394                            file_digest);
0395     if (!fsverity_info_cachep)
0396         return -ENOMEM;
0397     return 0;
0398 }
0399 
0400 void __init fsverity_exit_info_cache(void)
0401 {
0402     kmem_cache_destroy(fsverity_info_cachep);
0403     fsverity_info_cachep = NULL;
0404 }