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" 827603a60SMatthias 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 is_trusted_verity_target(struct dm_target * ti)15b6c1c574SMatthias Kaehlckestatic bool is_trusted_verity_target(struct dm_target *ti) 16b6c1c574SMatthias Kaehlcke { 17916ef623SMatthias Kaehlcke int verity_mode; 18b6c1c574SMatthias Kaehlcke u8 *root_digest; 19b6c1c574SMatthias Kaehlcke unsigned int digest_size; 20b6c1c574SMatthias Kaehlcke struct dm_verity_loadpin_trusted_root_digest *trd; 21b6c1c574SMatthias Kaehlcke bool trusted = false; 22b6c1c574SMatthias Kaehlcke 23b6c1c574SMatthias Kaehlcke if (!dm_is_verity_target(ti)) 24b6c1c574SMatthias Kaehlcke return false; 25b6c1c574SMatthias Kaehlcke 26916ef623SMatthias Kaehlcke verity_mode = dm_verity_get_mode(ti); 27916ef623SMatthias Kaehlcke 28916ef623SMatthias Kaehlcke if ((verity_mode != DM_VERITY_MODE_EIO) && 29916ef623SMatthias Kaehlcke (verity_mode != DM_VERITY_MODE_RESTART) && 30916ef623SMatthias Kaehlcke (verity_mode != DM_VERITY_MODE_PANIC)) 31916ef623SMatthias Kaehlcke return false; 32916ef623SMatthias Kaehlcke 33b6c1c574SMatthias Kaehlcke if (dm_verity_get_root_digest(ti, &root_digest, &digest_size)) 34b6c1c574SMatthias Kaehlcke return false; 35b6c1c574SMatthias Kaehlcke 36b6c1c574SMatthias Kaehlcke list_for_each_entry(trd, &dm_verity_loadpin_trusted_root_digests, node) { 37b6c1c574SMatthias Kaehlcke if ((trd->len == digest_size) && 38b6c1c574SMatthias Kaehlcke !memcmp(trd->data, root_digest, digest_size)) { 39b6c1c574SMatthias Kaehlcke trusted = true; 40b6c1c574SMatthias Kaehlcke break; 41b6c1c574SMatthias Kaehlcke } 42b6c1c574SMatthias Kaehlcke } 43b6c1c574SMatthias Kaehlcke 44b6c1c574SMatthias Kaehlcke kfree(root_digest); 45b6c1c574SMatthias Kaehlcke 46b6c1c574SMatthias Kaehlcke return trusted; 47b6c1c574SMatthias Kaehlcke } 48b6c1c574SMatthias Kaehlcke 49b6c1c574SMatthias Kaehlcke /* 50b6c1c574SMatthias Kaehlcke * Determines whether the file system of a superblock is located on 51b6c1c574SMatthias Kaehlcke * a verity device that is trusted by LoadPin. 52b6c1c574SMatthias Kaehlcke */ dm_verity_loadpin_is_bdev_trusted(struct block_device * bdev)53b6c1c574SMatthias Kaehlckebool dm_verity_loadpin_is_bdev_trusted(struct block_device *bdev) 54b6c1c574SMatthias Kaehlcke { 55b6c1c574SMatthias Kaehlcke struct mapped_device *md; 56b6c1c574SMatthias Kaehlcke struct dm_table *table; 57b6c1c574SMatthias Kaehlcke struct dm_target *ti; 58b6c1c574SMatthias Kaehlcke int srcu_idx; 59b6c1c574SMatthias Kaehlcke bool trusted = false; 60b6c1c574SMatthias Kaehlcke 61*47f04616SMatthias Kaehlcke if (bdev == NULL) 62*47f04616SMatthias Kaehlcke return false; 63*47f04616SMatthias Kaehlcke 64b6c1c574SMatthias Kaehlcke if (list_empty(&dm_verity_loadpin_trusted_root_digests)) 65b6c1c574SMatthias Kaehlcke return false; 66b6c1c574SMatthias Kaehlcke 67b6c1c574SMatthias Kaehlcke md = dm_get_md(bdev->bd_dev); 68b6c1c574SMatthias Kaehlcke if (!md) 69b6c1c574SMatthias Kaehlcke return false; 70b6c1c574SMatthias Kaehlcke 71b6c1c574SMatthias Kaehlcke table = dm_get_live_table(md, &srcu_idx); 72b6c1c574SMatthias Kaehlcke 7327603a60SMatthias Kaehlcke if (table->num_targets != 1) 74b6c1c574SMatthias Kaehlcke goto out; 75b6c1c574SMatthias Kaehlcke 76b6c1c574SMatthias Kaehlcke ti = dm_table_get_target(table, 0); 77b6c1c574SMatthias Kaehlcke 78b6c1c574SMatthias Kaehlcke if (is_trusted_verity_target(ti)) 79b6c1c574SMatthias Kaehlcke trusted = true; 80b6c1c574SMatthias Kaehlcke 81b6c1c574SMatthias Kaehlcke out: 82b6c1c574SMatthias Kaehlcke dm_put_live_table(md, srcu_idx); 83b6c1c574SMatthias Kaehlcke dm_put(md); 84b6c1c574SMatthias Kaehlcke 85b6c1c574SMatthias Kaehlcke return trusted; 86b6c1c574SMatthias Kaehlcke } 87