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