1 // SPDX-License-Identifier: GPL-2.0 1 2 /* 3 * Opening fs-verity files 4 * 5 * Copyright 2019 Google LLC 6 */ 7 8 #include "fsverity_private.h" 9 10 #include <linux/mm.h> 11 #include <linux/slab.h> 12 13 static struct kmem_cache *fsverity_info_cachep 14 15 /** 16 * fsverity_init_merkle_tree_params() - initia 17 * @params: the parameters struct to initializ 18 * @inode: the inode for which the Merkle tree 19 * @hash_algorithm: number of hash algorithm t 20 * @log_blocksize: log base 2 of block size to 21 * @salt: pointer to salt (optional) 22 * @salt_size: size of salt, possibly 0 23 * 24 * Validate the hash algorithm and block size, 25 * (num levels, num blocks in each level, etc. 26 * 27 * Return: 0 on success, -errno on failure 28 */ 29 int fsverity_init_merkle_tree_params(struct me 30 const str 31 unsigned 32 unsigned 33 const u8 34 { 35 const struct fsverity_hash_alg *hash_a 36 int err; 37 u64 blocks; 38 u64 blocks_in_level[FS_VERITY_MAX_LEVE 39 u64 offset; 40 int level; 41 42 memset(params, 0, sizeof(*params)); 43 44 hash_alg = fsverity_get_hash_alg(inode 45 if (IS_ERR(hash_alg)) 46 return PTR_ERR(hash_alg); 47 params->hash_alg = hash_alg; 48 params->digest_size = hash_alg->digest 49 50 params->hashstate = fsverity_prepare_h 51 52 if (IS_ERR(params->hashstate)) { 53 err = PTR_ERR(params->hashstat 54 params->hashstate = NULL; 55 fsverity_err(inode, "Error %d 56 goto out_err; 57 } 58 59 /* 60 * fs/verity/ directly assumes that th 61 * power of 2 less than or equal to PA 62 * arises from the interaction between 63 * themselves: filesystems expect to b 64 * filesystem block of data at a time. 65 * size must also be less than or equa 66 * 67 * The above are the only hard limitat 68 * block size could be as small as twi 69 * that's not useful, and it would res 70 * large Merkle trees. So we currentl 71 * block size be at least 1024 bytes. 72 * sub-page block case on systems with 73 */ 74 if (log_blocksize < 10 || log_blocksiz 75 log_blocksize > inode->i_blkbits) 76 fsverity_warn(inode, "Unsuppor 77 log_blocksize); 78 err = -EINVAL; 79 goto out_err; 80 } 81 params->log_blocksize = log_blocksize; 82 params->block_size = 1 << log_blocksiz 83 params->log_blocks_per_page = PAGE_SHI 84 params->blocks_per_page = 1 << params- 85 86 if (WARN_ON_ONCE(!is_power_of_2(params 87 err = -EINVAL; 88 goto out_err; 89 } 90 if (params->block_size < 2 * params->d 91 fsverity_warn(inode, 92 "Merkle tree blo 93 params->block_si 94 err = -EINVAL; 95 goto out_err; 96 } 97 params->log_digestsize = ilog2(params- 98 params->log_arity = log_blocksize - pa 99 params->hashes_per_block = 1 << params 100 101 /* 102 * Compute the number of levels in the 103 * level to the starting block of that 104 * the root and is stored first. Leve 105 * the data blocks and is stored last. 106 */ 107 108 /* Compute number of levels and the nu 109 blocks = ((u64)inode->i_size + params- 110 while (blocks > 1) { 111 if (params->num_levels >= FS_V 112 fsverity_err(inode, "T 113 err = -EFBIG; 114 goto out_err; 115 } 116 blocks = (blocks + params->has 117 params->log_arity; 118 blocks_in_level[params->num_le 119 } 120 121 /* Compute the starting block of each 122 offset = 0; 123 for (level = (int)params->num_levels - 124 params->level_start[level] = o 125 offset += blocks_in_level[leve 126 } 127 128 /* 129 * With block_size != PAGE_SIZE, an in 130 * allocated to track the "verified" s 131 * this bitmap to get too large. For 132 * limits the file size to about 4.4 T 133 * 134 * Together with the fact that the dat 135 * cannot have more than ULONG_MAX pag 136 * indices can always fit in an 'unsig 137 * explicitly check for that too. Not 138 * indices; data block indices might n 139 */ 140 if ((params->block_size != PAGE_SIZE & 141 offset > ULONG_MAX) { 142 fsverity_err(inode, "Too many 143 err = -EFBIG; 144 goto out_err; 145 } 146 147 params->tree_size = offset << log_bloc 148 params->tree_pages = PAGE_ALIGN(params 149 return 0; 150 151 out_err: 152 kfree(params->hashstate); 153 memset(params, 0, sizeof(*params)); 154 return err; 155 } 156 157 /* 158 * Compute the file digest by hashing the fsve 159 * builtin signature and with the sig_size fie 160 */ 161 static int compute_file_digest(const struct fs 162 struct fsverity 163 u8 *file_digest 164 { 165 __le32 sig_size = desc->sig_size; 166 int err; 167 168 desc->sig_size = 0; 169 err = fsverity_hash_buffer(hash_alg, d 170 desc->sig_size = sig_size; 171 172 return err; 173 } 174 175 /* 176 * Create a new fsverity_info from the given f 177 * appended builtin signature), and check the 178 * fsverity_descriptor must have already under 179 */ 180 struct fsverity_info *fsverity_create_info(con 181 str 182 { 183 struct fsverity_info *vi; 184 int err; 185 186 vi = kmem_cache_zalloc(fsverity_info_c 187 if (!vi) 188 return ERR_PTR(-ENOMEM); 189 vi->inode = inode; 190 191 err = fsverity_init_merkle_tree_params 192 193 194 195 if (err) { 196 fsverity_err(inode, 197 "Error %d initial 198 err); 199 goto fail; 200 } 201 202 memcpy(vi->root_hash, desc->root_hash, 203 204 err = compute_file_digest(vi->tree_par 205 vi->file_dig 206 if (err) { 207 fsverity_err(inode, "Error %d 208 goto fail; 209 } 210 211 err = fsverity_verify_signature(vi, de 212 le32_t 213 if (err) 214 goto fail; 215 216 if (vi->tree_params.block_size != PAGE 217 /* 218 * When the Merkle tree block 219 * a bitmap to keep track of w 220 * verified. This bitmap must 221 * including alignment to a pa 222 * 223 * Eventually, to support extr 224 * way, it might be necessary 225 * reclaimable. But for now, 226 * is a simple solution that w 227 * fsverity is realistically u 228 * blocks, a 100MB file only n 229 * bitmap for any file under 1 230 */ 231 unsigned long num_bits = 232 vi->tree_params.tree_p 233 vi->tree_params.log_bl 234 235 vi->hash_block_verified = kvca 236 237 238 if (!vi->hash_block_verified) 239 err = -ENOMEM; 240 goto fail; 241 } 242 } 243 244 return vi; 245 246 fail: 247 fsverity_free_info(vi); 248 return ERR_PTR(err); 249 } 250 251 void fsverity_set_info(struct inode *inode, st 252 { 253 /* 254 * Multiple tasks may race to set ->i_ 255 * cmpxchg_release(). This pairs with 256 * fsverity_get_info(). I.e., here we 257 * RELEASE barrier so that other tasks 258 */ 259 if (cmpxchg_release(&inode->i_verity_i 260 /* Lost the race, so free the 261 fsverity_free_info(vi); 262 /* 263 * Afterwards, the caller may 264 * so make sure to ACQUIRE the 265 */ 266 (void)fsverity_get_info(inode) 267 } 268 } 269 270 void fsverity_free_info(struct fsverity_info * 271 { 272 if (!vi) 273 return; 274 kfree(vi->tree_params.hashstate); 275 kvfree(vi->hash_block_verified); 276 kmem_cache_free(fsverity_info_cachep, 277 } 278 279 static bool validate_fsverity_descriptor(struc 280 const 281 size_ 282 { 283 if (desc_size < sizeof(*desc)) { 284 fsverity_err(inode, "Unrecogni 285 desc_size); 286 return false; 287 } 288 289 if (desc->version != 1) { 290 fsverity_err(inode, "Unrecogni 291 desc->version); 292 return false; 293 } 294 295 if (memchr_inv(desc->__reserved, 0, si 296 fsverity_err(inode, "Reserved 297 return false; 298 } 299 300 if (desc->salt_size > sizeof(desc->sal 301 fsverity_err(inode, "Invalid s 302 return false; 303 } 304 305 if (le64_to_cpu(desc->data_size) != in 306 fsverity_err(inode, 307 "Wrong data_size: 308 le64_to_cpu(desc- 309 return false; 310 } 311 312 if (le32_to_cpu(desc->sig_size) > desc 313 fsverity_err(inode, "Signature 314 return false; 315 } 316 317 return true; 318 } 319 320 /* 321 * Read the inode's fsverity_descriptor (with 322 * signature) from the filesystem, and do basi 323 */ 324 int fsverity_get_descriptor(struct inode *inod 325 struct fsverity_de 326 { 327 int res; 328 struct fsverity_descriptor *desc; 329 330 res = inode->i_sb->s_vop->get_verity_d 331 if (res < 0) { 332 fsverity_err(inode, 333 "Error %d getting 334 return res; 335 } 336 if (res > FS_VERITY_MAX_DESCRIPTOR_SIZ 337 fsverity_err(inode, "Verity de 338 res); 339 return -EMSGSIZE; 340 } 341 desc = kmalloc(res, GFP_KERNEL); 342 if (!desc) 343 return -ENOMEM; 344 res = inode->i_sb->s_vop->get_verity_d 345 if (res < 0) { 346 fsverity_err(inode, "Error %d 347 kfree(desc); 348 return res; 349 } 350 351 if (!validate_fsverity_descriptor(inod 352 kfree(desc); 353 return -EINVAL; 354 } 355 356 *desc_ret = desc; 357 return 0; 358 } 359 360 /* Ensure the inode has an ->i_verity_info */ 361 static int ensure_verity_info(struct inode *in 362 { 363 struct fsverity_info *vi = fsverity_ge 364 struct fsverity_descriptor *desc; 365 int err; 366 367 if (vi) 368 return 0; 369 370 err = fsverity_get_descriptor(inode, & 371 if (err) 372 return err; 373 374 vi = fsverity_create_info(inode, desc) 375 if (IS_ERR(vi)) { 376 err = PTR_ERR(vi); 377 goto out_free_desc; 378 } 379 380 fsverity_set_info(inode, vi); 381 err = 0; 382 out_free_desc: 383 kfree(desc); 384 return err; 385 } 386 387 int __fsverity_file_open(struct inode *inode, 388 { 389 if (filp->f_mode & FMODE_WRITE) 390 return -EPERM; 391 return ensure_verity_info(inode); 392 } 393 EXPORT_SYMBOL_GPL(__fsverity_file_open); 394 395 int __fsverity_prepare_setattr(struct dentry * 396 { 397 if (attr->ia_valid & ATTR_SIZE) 398 return -EPERM; 399 return 0; 400 } 401 EXPORT_SYMBOL_GPL(__fsverity_prepare_setattr); 402 403 void __fsverity_cleanup_inode(struct inode *in 404 { 405 fsverity_free_info(inode->i_verity_inf 406 inode->i_verity_info = NULL; 407 } 408 EXPORT_SYMBOL_GPL(__fsverity_cleanup_inode); 409 410 void __init fsverity_init_info_cache(void) 411 { 412 fsverity_info_cachep = KMEM_CACHE_USER 413 fsveri 414 SLAB_R 415 file_d 416 } 417
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.