root/fs/verity/open.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fsverity_init_merkle_tree_params
  2. compute_file_measurement
  3. fsverity_create_info
  4. fsverity_set_info
  5. fsverity_free_info
  6. ensure_verity_info
  7. fsverity_file_open
  8. fsverity_prepare_setattr
  9. fsverity_cleanup_inode
  10. fsverity_init_info_cache
  11. fsverity_exit_info_cache

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * fs/verity/open.c: opening fs-verity files
   4  *
   5  * Copyright 2019 Google LLC
   6  */
   7 
   8 #include "fsverity_private.h"
   9 
  10 #include <linux/slab.h>
  11 
  12 static struct kmem_cache *fsverity_info_cachep;
  13 
  14 /**
  15  * fsverity_init_merkle_tree_params() - initialize Merkle tree parameters
  16  * @params: the parameters struct to initialize
  17  * @inode: the inode for which the Merkle tree is being built
  18  * @hash_algorithm: number of hash algorithm to use
  19  * @log_blocksize: log base 2 of block size to use
  20  * @salt: pointer to salt (optional)
  21  * @salt_size: size of salt, possibly 0
  22  *
  23  * Validate the hash algorithm and block size, then compute the tree topology
  24  * (num levels, num blocks in each level, etc.) and initialize @params.
  25  *
  26  * Return: 0 on success, -errno on failure
  27  */
  28 int fsverity_init_merkle_tree_params(struct merkle_tree_params *params,
  29                                      const struct inode *inode,
  30                                      unsigned int hash_algorithm,
  31                                      unsigned int log_blocksize,
  32                                      const u8 *salt, size_t salt_size)
  33 {
  34         const struct fsverity_hash_alg *hash_alg;
  35         int err;
  36         u64 blocks;
  37         u64 offset;
  38         int level;
  39 
  40         memset(params, 0, sizeof(*params));
  41 
  42         hash_alg = fsverity_get_hash_alg(inode, hash_algorithm);
  43         if (IS_ERR(hash_alg))
  44                 return PTR_ERR(hash_alg);
  45         params->hash_alg = hash_alg;
  46         params->digest_size = hash_alg->digest_size;
  47 
  48         params->hashstate = fsverity_prepare_hash_state(hash_alg, salt,
  49                                                         salt_size);
  50         if (IS_ERR(params->hashstate)) {
  51                 err = PTR_ERR(params->hashstate);
  52                 params->hashstate = NULL;
  53                 fsverity_err(inode, "Error %d preparing hash state", err);
  54                 goto out_err;
  55         }
  56 
  57         if (log_blocksize != PAGE_SHIFT) {
  58                 fsverity_warn(inode, "Unsupported log_blocksize: %u",
  59                               log_blocksize);
  60                 err = -EINVAL;
  61                 goto out_err;
  62         }
  63         params->log_blocksize = log_blocksize;
  64         params->block_size = 1 << log_blocksize;
  65 
  66         if (WARN_ON(!is_power_of_2(params->digest_size))) {
  67                 err = -EINVAL;
  68                 goto out_err;
  69         }
  70         if (params->block_size < 2 * params->digest_size) {
  71                 fsverity_warn(inode,
  72                               "Merkle tree block size (%u) too small for hash algorithm \"%s\"",
  73                               params->block_size, hash_alg->name);
  74                 err = -EINVAL;
  75                 goto out_err;
  76         }
  77         params->log_arity = params->log_blocksize - ilog2(params->digest_size);
  78         params->hashes_per_block = 1 << params->log_arity;
  79 
  80         pr_debug("Merkle tree uses %s with %u-byte blocks (%u hashes/block), salt=%*phN\n",
  81                  hash_alg->name, params->block_size, params->hashes_per_block,
  82                  (int)salt_size, salt);
  83 
  84         /*
  85          * Compute the number of levels in the Merkle tree and create a map from
  86          * level to the starting block of that level.  Level 'num_levels - 1' is
  87          * the root and is stored first.  Level 0 is the level directly "above"
  88          * the data blocks and is stored last.
  89          */
  90 
  91         /* Compute number of levels and the number of blocks in each level */
  92         blocks = (inode->i_size + params->block_size - 1) >> log_blocksize;
  93         pr_debug("Data is %lld bytes (%llu blocks)\n", inode->i_size, blocks);
  94         while (blocks > 1) {
  95                 if (params->num_levels >= FS_VERITY_MAX_LEVELS) {
  96                         fsverity_err(inode, "Too many levels in Merkle tree");
  97                         err = -EINVAL;
  98                         goto out_err;
  99                 }
 100                 blocks = (blocks + params->hashes_per_block - 1) >>
 101                          params->log_arity;
 102                 /* temporarily using level_start[] to store blocks in level */
 103                 params->level_start[params->num_levels++] = blocks;
 104         }
 105 
 106         /* Compute the starting block of each level */
 107         offset = 0;
 108         for (level = (int)params->num_levels - 1; level >= 0; level--) {
 109                 blocks = params->level_start[level];
 110                 params->level_start[level] = offset;
 111                 pr_debug("Level %d is %llu blocks starting at index %llu\n",
 112                          level, blocks, offset);
 113                 offset += blocks;
 114         }
 115 
 116         params->tree_size = offset << log_blocksize;
 117         return 0;
 118 
 119 out_err:
 120         kfree(params->hashstate);
 121         memset(params, 0, sizeof(*params));
 122         return err;
 123 }
 124 
 125 /*
 126  * Compute the file measurement by hashing the fsverity_descriptor excluding the
 127  * signature and with the sig_size field set to 0.
 128  */
 129 static int compute_file_measurement(const struct fsverity_hash_alg *hash_alg,
 130                                     struct fsverity_descriptor *desc,
 131                                     u8 *measurement)
 132 {
 133         __le32 sig_size = desc->sig_size;
 134         int err;
 135 
 136         desc->sig_size = 0;
 137         err = fsverity_hash_buffer(hash_alg, desc, sizeof(*desc), measurement);
 138         desc->sig_size = sig_size;
 139 
 140         return err;
 141 }
 142 
 143 /*
 144  * Validate the given fsverity_descriptor and create a new fsverity_info from
 145  * it.  The signature (if present) is also checked.
 146  */
 147 struct fsverity_info *fsverity_create_info(const struct inode *inode,
 148                                            void *_desc, size_t desc_size)
 149 {
 150         struct fsverity_descriptor *desc = _desc;
 151         struct fsverity_info *vi;
 152         int err;
 153 
 154         if (desc_size < sizeof(*desc)) {
 155                 fsverity_err(inode, "Unrecognized descriptor size: %zu bytes",
 156                              desc_size);
 157                 return ERR_PTR(-EINVAL);
 158         }
 159 
 160         if (desc->version != 1) {
 161                 fsverity_err(inode, "Unrecognized descriptor version: %u",
 162                              desc->version);
 163                 return ERR_PTR(-EINVAL);
 164         }
 165 
 166         if (memchr_inv(desc->__reserved, 0, sizeof(desc->__reserved))) {
 167                 fsverity_err(inode, "Reserved bits set in descriptor");
 168                 return ERR_PTR(-EINVAL);
 169         }
 170 
 171         if (desc->salt_size > sizeof(desc->salt)) {
 172                 fsverity_err(inode, "Invalid salt_size: %u", desc->salt_size);
 173                 return ERR_PTR(-EINVAL);
 174         }
 175 
 176         if (le64_to_cpu(desc->data_size) != inode->i_size) {
 177                 fsverity_err(inode,
 178                              "Wrong data_size: %llu (desc) != %lld (inode)",
 179                              le64_to_cpu(desc->data_size), inode->i_size);
 180                 return ERR_PTR(-EINVAL);
 181         }
 182 
 183         vi = kmem_cache_zalloc(fsverity_info_cachep, GFP_KERNEL);
 184         if (!vi)
 185                 return ERR_PTR(-ENOMEM);
 186         vi->inode = inode;
 187 
 188         err = fsverity_init_merkle_tree_params(&vi->tree_params, inode,
 189                                                desc->hash_algorithm,
 190                                                desc->log_blocksize,
 191                                                desc->salt, desc->salt_size);
 192         if (err) {
 193                 fsverity_err(inode,
 194                              "Error %d initializing Merkle tree parameters",
 195                              err);
 196                 goto out;
 197         }
 198 
 199         memcpy(vi->root_hash, desc->root_hash, vi->tree_params.digest_size);
 200 
 201         err = compute_file_measurement(vi->tree_params.hash_alg, desc,
 202                                        vi->measurement);
 203         if (err) {
 204                 fsverity_err(inode, "Error %d computing file measurement", err);
 205                 goto out;
 206         }
 207         pr_debug("Computed file measurement: %s:%*phN\n",
 208                  vi->tree_params.hash_alg->name,
 209                  vi->tree_params.digest_size, vi->measurement);
 210 
 211         err = fsverity_verify_signature(vi, desc, desc_size);
 212 out:
 213         if (err) {
 214                 fsverity_free_info(vi);
 215                 vi = ERR_PTR(err);
 216         }
 217         return vi;
 218 }
 219 
 220 void fsverity_set_info(struct inode *inode, struct fsverity_info *vi)
 221 {
 222         /*
 223          * Multiple processes may race to set ->i_verity_info, so use cmpxchg.
 224          * This pairs with the READ_ONCE() in fsverity_get_info().
 225          */
 226         if (cmpxchg(&inode->i_verity_info, NULL, vi) != NULL)
 227                 fsverity_free_info(vi);
 228 }
 229 
 230 void fsverity_free_info(struct fsverity_info *vi)
 231 {
 232         if (!vi)
 233                 return;
 234         kfree(vi->tree_params.hashstate);
 235         kmem_cache_free(fsverity_info_cachep, vi);
 236 }
 237 
 238 /* Ensure the inode has an ->i_verity_info */
 239 static int ensure_verity_info(struct inode *inode)
 240 {
 241         struct fsverity_info *vi = fsverity_get_info(inode);
 242         struct fsverity_descriptor *desc;
 243         int res;
 244 
 245         if (vi)
 246                 return 0;
 247 
 248         res = inode->i_sb->s_vop->get_verity_descriptor(inode, NULL, 0);
 249         if (res < 0) {
 250                 fsverity_err(inode,
 251                              "Error %d getting verity descriptor size", res);
 252                 return res;
 253         }
 254         if (res > FS_VERITY_MAX_DESCRIPTOR_SIZE) {
 255                 fsverity_err(inode, "Verity descriptor is too large (%d bytes)",
 256                              res);
 257                 return -EMSGSIZE;
 258         }
 259         desc = kmalloc(res, GFP_KERNEL);
 260         if (!desc)
 261                 return -ENOMEM;
 262         res = inode->i_sb->s_vop->get_verity_descriptor(inode, desc, res);
 263         if (res < 0) {
 264                 fsverity_err(inode, "Error %d reading verity descriptor", res);
 265                 goto out_free_desc;
 266         }
 267 
 268         vi = fsverity_create_info(inode, desc, res);
 269         if (IS_ERR(vi)) {
 270                 res = PTR_ERR(vi);
 271                 goto out_free_desc;
 272         }
 273 
 274         fsverity_set_info(inode, vi);
 275         res = 0;
 276 out_free_desc:
 277         kfree(desc);
 278         return res;
 279 }
 280 
 281 /**
 282  * fsverity_file_open() - prepare to open a verity file
 283  * @inode: the inode being opened
 284  * @filp: the struct file being set up
 285  *
 286  * When opening a verity file, deny the open if it is for writing.  Otherwise,
 287  * set up the inode's ->i_verity_info if not already done.
 288  *
 289  * When combined with fscrypt, this must be called after fscrypt_file_open().
 290  * Otherwise, we won't have the key set up to decrypt the verity metadata.
 291  *
 292  * Return: 0 on success, -errno on failure
 293  */
 294 int fsverity_file_open(struct inode *inode, struct file *filp)
 295 {
 296         if (!IS_VERITY(inode))
 297                 return 0;
 298 
 299         if (filp->f_mode & FMODE_WRITE) {
 300                 pr_debug("Denying opening verity file (ino %lu) for write\n",
 301                          inode->i_ino);
 302                 return -EPERM;
 303         }
 304 
 305         return ensure_verity_info(inode);
 306 }
 307 EXPORT_SYMBOL_GPL(fsverity_file_open);
 308 
 309 /**
 310  * fsverity_prepare_setattr() - prepare to change a verity inode's attributes
 311  * @dentry: dentry through which the inode is being changed
 312  * @attr: attributes to change
 313  *
 314  * Verity files are immutable, so deny truncates.  This isn't covered by the
 315  * open-time check because sys_truncate() takes a path, not a file descriptor.
 316  *
 317  * Return: 0 on success, -errno on failure
 318  */
 319 int fsverity_prepare_setattr(struct dentry *dentry, struct iattr *attr)
 320 {
 321         if (IS_VERITY(d_inode(dentry)) && (attr->ia_valid & ATTR_SIZE)) {
 322                 pr_debug("Denying truncate of verity file (ino %lu)\n",
 323                          d_inode(dentry)->i_ino);
 324                 return -EPERM;
 325         }
 326         return 0;
 327 }
 328 EXPORT_SYMBOL_GPL(fsverity_prepare_setattr);
 329 
 330 /**
 331  * fsverity_cleanup_inode() - free the inode's verity info, if present
 332  *
 333  * Filesystems must call this on inode eviction to free ->i_verity_info.
 334  */
 335 void fsverity_cleanup_inode(struct inode *inode)
 336 {
 337         fsverity_free_info(inode->i_verity_info);
 338         inode->i_verity_info = NULL;
 339 }
 340 EXPORT_SYMBOL_GPL(fsverity_cleanup_inode);
 341 
 342 int __init fsverity_init_info_cache(void)
 343 {
 344         fsverity_info_cachep = KMEM_CACHE_USERCOPY(fsverity_info,
 345                                                    SLAB_RECLAIM_ACCOUNT,
 346                                                    measurement);
 347         if (!fsverity_info_cachep)
 348                 return -ENOMEM;
 349         return 0;
 350 }
 351 
 352 void __init fsverity_exit_info_cache(void)
 353 {
 354         kmem_cache_destroy(fsverity_info_cachep);
 355         fsverity_info_cachep = NULL;
 356 }

/* [<][>][^][v][top][bottom][index][help] */