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