forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-10-12 a5969cabbb4660eab42b6ef0412cbbd1200cf14d
kernel/fs/ubifs/master.c
....@@ -1,20 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * This file is part of UBIFS.
34 *
45 * Copyright (C) 2006-2008 Nokia Corporation.
5
- *
6
- * This program is free software; you can redistribute it and/or modify it
7
- * under the terms of the GNU General Public License version 2 as published by
8
- * the Free Software Foundation.
9
- *
10
- * This program is distributed in the hope that it will be useful, but WITHOUT
11
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13
- * more details.
14
- *
15
- * You should have received a copy of the GNU General Public License along with
16
- * this program; if not, write to the Free Software Foundation, Inc., 51
17
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
186 *
197 * Authors: Artem Bityutskiy (Битюцкий Артём)
208 * Adrian Hunter
....@@ -23,6 +11,72 @@
2311 /* This file implements reading and writing the master node */
2412
2513 #include "ubifs.h"
14
+
15
+/**
16
+ * ubifs_compare_master_node - compare two UBIFS master nodes
17
+ * @c: UBIFS file-system description object
18
+ * @m1: the first node
19
+ * @m2: the second node
20
+ *
21
+ * This function compares two UBIFS master nodes. Returns 0 if they are equal
22
+ * and nonzero if not.
23
+ */
24
+int ubifs_compare_master_node(struct ubifs_info *c, void *m1, void *m2)
25
+{
26
+ int ret;
27
+ int behind;
28
+ int hmac_offs = offsetof(struct ubifs_mst_node, hmac);
29
+
30
+ /*
31
+ * Do not compare the common node header since the sequence number and
32
+ * hence the CRC are different.
33
+ */
34
+ ret = memcmp(m1 + UBIFS_CH_SZ, m2 + UBIFS_CH_SZ,
35
+ hmac_offs - UBIFS_CH_SZ);
36
+ if (ret)
37
+ return ret;
38
+
39
+ /*
40
+ * Do not compare the embedded HMAC aswell which also must be different
41
+ * due to the different common node header.
42
+ */
43
+ behind = hmac_offs + UBIFS_MAX_HMAC_LEN;
44
+
45
+ if (UBIFS_MST_NODE_SZ > behind)
46
+ return memcmp(m1 + behind, m2 + behind, UBIFS_MST_NODE_SZ - behind);
47
+
48
+ return 0;
49
+}
50
+
51
+/* mst_node_check_hash - Check hash of a master node
52
+ * @c: UBIFS file-system description object
53
+ * @mst: The master node
54
+ * @expected: The expected hash of the master node
55
+ *
56
+ * This checks the hash of a master node against a given expected hash.
57
+ * Note that we have two master nodes on a UBIFS image which have different
58
+ * sequence numbers and consequently different CRCs. To be able to match
59
+ * both master nodes we exclude the common node header containing the sequence
60
+ * number and CRC from the hash.
61
+ *
62
+ * Returns 0 if the hashes are equal, a negative error code otherwise.
63
+ */
64
+static int mst_node_check_hash(const struct ubifs_info *c,
65
+ const struct ubifs_mst_node *mst,
66
+ const u8 *expected)
67
+{
68
+ u8 calc[UBIFS_MAX_HASH_LEN];
69
+ const void *node = mst;
70
+
71
+ crypto_shash_tfm_digest(c->hash_tfm, node + sizeof(struct ubifs_ch),
72
+ UBIFS_MST_NODE_SZ - sizeof(struct ubifs_ch),
73
+ calc);
74
+
75
+ if (ubifs_check_hash(c, expected, calc))
76
+ return -EPERM;
77
+
78
+ return 0;
79
+}
2680
2781 /**
2882 * scan_for_master - search the valid master node.
....@@ -37,7 +91,7 @@
3791 {
3892 struct ubifs_scan_leb *sleb;
3993 struct ubifs_scan_node *snod;
40
- int lnum, offs = 0, nodes_cnt;
94
+ int lnum, offs = 0, nodes_cnt, err;
4195
4296 lnum = UBIFS_MST_LNUM;
4397
....@@ -69,12 +123,31 @@
69123 goto out_dump;
70124 if (snod->offs != offs)
71125 goto out;
72
- if (memcmp((void *)c->mst_node + UBIFS_CH_SZ,
73
- (void *)snod->node + UBIFS_CH_SZ,
74
- UBIFS_MST_NODE_SZ - UBIFS_CH_SZ))
126
+ if (ubifs_compare_master_node(c, c->mst_node, snod->node))
75127 goto out;
128
+
76129 c->mst_offs = offs;
77130 ubifs_scan_destroy(sleb);
131
+
132
+ if (!ubifs_authenticated(c))
133
+ return 0;
134
+
135
+ if (ubifs_hmac_zero(c, c->mst_node->hmac)) {
136
+ err = mst_node_check_hash(c, c->mst_node,
137
+ c->sup_node->hash_mst);
138
+ if (err)
139
+ ubifs_err(c, "Failed to verify master node hash");
140
+ } else {
141
+ err = ubifs_node_verify_hmac(c, c->mst_node,
142
+ sizeof(struct ubifs_mst_node),
143
+ offsetof(struct ubifs_mst_node, hmac));
144
+ if (err)
145
+ ubifs_err(c, "Failed to verify master node HMAC");
146
+ }
147
+
148
+ if (err)
149
+ return -EPERM;
150
+
78151 return 0;
79152
80153 out:
....@@ -305,6 +378,8 @@
305378 c->lst.total_dead = le64_to_cpu(c->mst_node->total_dead);
306379 c->lst.total_dark = le64_to_cpu(c->mst_node->total_dark);
307380
381
+ ubifs_copy_hash(c, c->mst_node->hash_root_idx, c->zroot.hash);
382
+
308383 c->calc_idx_sz = c->bi.old_idx_sz;
309384
310385 if (c->mst_node->flags & cpu_to_le32(UBIFS_MST_NO_ORPHS))
....@@ -378,7 +453,9 @@
378453 c->mst_offs = offs;
379454 c->mst_node->highest_inum = cpu_to_le64(c->highest_inum);
380455
381
- err = ubifs_write_node(c, c->mst_node, len, lnum, offs);
456
+ ubifs_copy_hash(c, c->zroot.hash, c->mst_node->hash_root_idx);
457
+ err = ubifs_write_node_hmac(c, c->mst_node, len, lnum, offs,
458
+ offsetof(struct ubifs_mst_node, hmac));
382459 if (err)
383460 return err;
384461
....@@ -389,7 +466,8 @@
389466 if (err)
390467 return err;
391468 }
392
- err = ubifs_write_node(c, c->mst_node, len, lnum, offs);
469
+ err = ubifs_write_node_hmac(c, c->mst_node, len, lnum, offs,
470
+ offsetof(struct ubifs_mst_node, hmac));
393471
394472 return err;
395473 }