1*b6c1c574SMatthias Kaehlcke // SPDX-License-Identifier: GPL-2.0-only 2*b6c1c574SMatthias Kaehlcke 3*b6c1c574SMatthias Kaehlcke #include <linux/list.h> 4*b6c1c574SMatthias Kaehlcke #include <linux/kernel.h> 5*b6c1c574SMatthias Kaehlcke #include <linux/dm-verity-loadpin.h> 6*b6c1c574SMatthias Kaehlcke 7*b6c1c574SMatthias Kaehlcke #include "dm.h" 8*b6c1c574SMatthias Kaehlcke #include "dm-verity.h" 9*b6c1c574SMatthias Kaehlcke 10*b6c1c574SMatthias Kaehlcke #define DM_MSG_PREFIX "verity-loadpin" 11*b6c1c574SMatthias Kaehlcke 12*b6c1c574SMatthias Kaehlcke LIST_HEAD(dm_verity_loadpin_trusted_root_digests); 13*b6c1c574SMatthias Kaehlcke 14*b6c1c574SMatthias Kaehlcke static bool is_trusted_verity_target(struct dm_target *ti) 15*b6c1c574SMatthias Kaehlcke { 16*b6c1c574SMatthias Kaehlcke u8 *root_digest; 17*b6c1c574SMatthias Kaehlcke unsigned int digest_size; 18*b6c1c574SMatthias Kaehlcke struct dm_verity_loadpin_trusted_root_digest *trd; 19*b6c1c574SMatthias Kaehlcke bool trusted = false; 20*b6c1c574SMatthias Kaehlcke 21*b6c1c574SMatthias Kaehlcke if (!dm_is_verity_target(ti)) 22*b6c1c574SMatthias Kaehlcke return false; 23*b6c1c574SMatthias Kaehlcke 24*b6c1c574SMatthias Kaehlcke if (dm_verity_get_root_digest(ti, &root_digest, &digest_size)) 25*b6c1c574SMatthias Kaehlcke return false; 26*b6c1c574SMatthias Kaehlcke 27*b6c1c574SMatthias Kaehlcke list_for_each_entry(trd, &dm_verity_loadpin_trusted_root_digests, node) { 28*b6c1c574SMatthias Kaehlcke if ((trd->len == digest_size) && 29*b6c1c574SMatthias Kaehlcke !memcmp(trd->data, root_digest, digest_size)) { 30*b6c1c574SMatthias Kaehlcke trusted = true; 31*b6c1c574SMatthias Kaehlcke break; 32*b6c1c574SMatthias Kaehlcke } 33*b6c1c574SMatthias Kaehlcke } 34*b6c1c574SMatthias Kaehlcke 35*b6c1c574SMatthias Kaehlcke kfree(root_digest); 36*b6c1c574SMatthias Kaehlcke 37*b6c1c574SMatthias Kaehlcke return trusted; 38*b6c1c574SMatthias Kaehlcke } 39*b6c1c574SMatthias Kaehlcke 40*b6c1c574SMatthias Kaehlcke /* 41*b6c1c574SMatthias Kaehlcke * Determines whether the file system of a superblock is located on 42*b6c1c574SMatthias Kaehlcke * a verity device that is trusted by LoadPin. 43*b6c1c574SMatthias Kaehlcke */ 44*b6c1c574SMatthias Kaehlcke bool dm_verity_loadpin_is_bdev_trusted(struct block_device *bdev) 45*b6c1c574SMatthias Kaehlcke { 46*b6c1c574SMatthias Kaehlcke struct mapped_device *md; 47*b6c1c574SMatthias Kaehlcke struct dm_table *table; 48*b6c1c574SMatthias Kaehlcke struct dm_target *ti; 49*b6c1c574SMatthias Kaehlcke int srcu_idx; 50*b6c1c574SMatthias Kaehlcke bool trusted = false; 51*b6c1c574SMatthias Kaehlcke 52*b6c1c574SMatthias Kaehlcke if (list_empty(&dm_verity_loadpin_trusted_root_digests)) 53*b6c1c574SMatthias Kaehlcke return false; 54*b6c1c574SMatthias Kaehlcke 55*b6c1c574SMatthias Kaehlcke md = dm_get_md(bdev->bd_dev); 56*b6c1c574SMatthias Kaehlcke if (!md) 57*b6c1c574SMatthias Kaehlcke return false; 58*b6c1c574SMatthias Kaehlcke 59*b6c1c574SMatthias Kaehlcke table = dm_get_live_table(md, &srcu_idx); 60*b6c1c574SMatthias Kaehlcke 61*b6c1c574SMatthias Kaehlcke if (dm_table_get_num_targets(table) != 1) 62*b6c1c574SMatthias Kaehlcke goto out; 63*b6c1c574SMatthias Kaehlcke 64*b6c1c574SMatthias Kaehlcke ti = dm_table_get_target(table, 0); 65*b6c1c574SMatthias Kaehlcke 66*b6c1c574SMatthias Kaehlcke if (is_trusted_verity_target(ti)) 67*b6c1c574SMatthias Kaehlcke trusted = true; 68*b6c1c574SMatthias Kaehlcke 69*b6c1c574SMatthias Kaehlcke out: 70*b6c1c574SMatthias Kaehlcke dm_put_live_table(md, srcu_idx); 71*b6c1c574SMatthias Kaehlcke dm_put(md); 72*b6c1c574SMatthias Kaehlcke 73*b6c1c574SMatthias Kaehlcke return trusted; 74*b6c1c574SMatthias Kaehlcke } 75