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