Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-only
2 : /*
3 : * This file is part of UBIFS.
4 : *
5 : * Copyright (C) 2006-2008 Nokia Corporation.
6 : *
7 : * Authors: Artem Bityutskiy (Битюцкий Артём)
8 : * Adrian Hunter
9 : */
10 :
11 : /* This file implements reading and writing the master node */
12 :
13 : #include "linux_err.h"
14 : #include "kmem.h"
15 : #include "ubifs.h"
16 : #include "defs.h"
17 : #include "debug.h"
18 :
19 : /**
20 : * ubifs_compare_master_node - compare two UBIFS master nodes
21 : * @c: UBIFS file-system description object
22 : * @m1: the first node
23 : * @m2: the second node
24 : *
25 : * This function compares two UBIFS master nodes. Returns 0 if they are equal
26 : * and nonzero if not.
27 : */
28 2259 : int ubifs_compare_master_node(__unused struct ubifs_info *c, void *m1, void *m2)
29 : {
30 : int ret;
31 : int behind;
32 2259 : int hmac_offs = offsetof(struct ubifs_mst_node, hmac);
33 :
34 : /*
35 : * Do not compare the common node header since the sequence number and
36 : * hence the CRC are different.
37 : */
38 2259 : ret = memcmp(m1 + UBIFS_CH_SZ, m2 + UBIFS_CH_SZ,
39 : hmac_offs - UBIFS_CH_SZ);
40 2259 : if (ret)
41 : return ret;
42 :
43 : /*
44 : * Do not compare the embedded HMAC as well which also must be different
45 : * due to the different common node header.
46 : */
47 2259 : behind = hmac_offs + UBIFS_MAX_HMAC_LEN;
48 :
49 : if (UBIFS_MST_NODE_SZ > behind)
50 2259 : return memcmp(m1 + behind, m2 + behind, UBIFS_MST_NODE_SZ - behind);
51 :
52 : return 0;
53 : }
54 :
55 : /* mst_node_check_hash - Check hash of a master node
56 : * @c: UBIFS file-system description object
57 : * @mst: The master node
58 : * @expected: The expected hash of the master node
59 : *
60 : * This checks the hash of a master node against a given expected hash.
61 : * Note that we have two master nodes on a UBIFS image which have different
62 : * sequence numbers and consequently different CRCs. To be able to match
63 : * both master nodes we exclude the common node header containing the sequence
64 : * number and CRC from the hash.
65 : *
66 : * Returns 0 if the hashes are equal, a negative error code otherwise.
67 : */
68 : static int mst_node_check_hash(__unused const struct ubifs_info *c,
69 : __unused const struct ubifs_mst_node *mst,
70 : __unused const u8 *expected)
71 : {
72 : // To be implemented
73 : return 0;
74 : }
75 :
76 : /**
77 : * scan_for_master - search the valid master node.
78 : * @c: UBIFS file-system description object
79 : *
80 : * This function scans the master node LEBs and search for the latest master
81 : * node. Returns zero in case of success, %-EUCLEAN if there master area is
82 : * corrupted and requires recovery, and a negative error code in case of
83 : * failure.
84 : */
85 2284 : static int scan_for_master(struct ubifs_info *c)
86 : {
87 : struct ubifs_scan_leb *sleb;
88 : struct ubifs_scan_node *snod;
89 2284 : int lnum, offs = 0, nodes_cnt, err;
90 :
91 2284 : lnum = UBIFS_MST_LNUM;
92 :
93 2284 : sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1);
94 2284 : if (IS_ERR(sleb))
95 4 : return PTR_ERR(sleb);
96 2280 : nodes_cnt = sleb->nodes_cnt;
97 2280 : if (nodes_cnt > 0) {
98 2278 : snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node,
99 : list);
100 2278 : if (snod->type != UBIFS_MST_NODE)
101 : goto out_dump;
102 2278 : memcpy(c->mst_node, snod->node, snod->len);
103 2278 : offs = snod->offs;
104 : }
105 2280 : ubifs_scan_destroy(sleb);
106 :
107 2280 : lnum += 1;
108 :
109 2280 : sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1);
110 2280 : if (IS_ERR(sleb))
111 5 : return PTR_ERR(sleb);
112 2275 : if (sleb->nodes_cnt != nodes_cnt)
113 : goto out;
114 2255 : if (!sleb->nodes_cnt)
115 : goto out;
116 2255 : snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, list);
117 2255 : if (snod->type != UBIFS_MST_NODE)
118 : goto out_dump;
119 2255 : if (snod->offs != offs)
120 : goto out;
121 2255 : if (ubifs_compare_master_node(c, c->mst_node, snod->node))
122 : goto out;
123 :
124 2255 : c->mst_offs = offs;
125 2255 : ubifs_scan_destroy(sleb);
126 :
127 2255 : if (!ubifs_authenticated(c))
128 : return 0;
129 :
130 : if (ubifs_hmac_zero(c, c->mst_node->hmac)) {
131 : err = mst_node_check_hash(c, c->mst_node,
132 : c->sup_node->hash_mst);
133 : if (err)
134 : ubifs_err(c, "Failed to verify master node hash");
135 : } else {
136 : err = ubifs_node_verify_hmac(c, c->mst_node,
137 : sizeof(struct ubifs_mst_node),
138 : offsetof(struct ubifs_mst_node, hmac));
139 : if (err)
140 : ubifs_err(c, "Failed to verify master node HMAC");
141 : }
142 :
143 : if (err)
144 : return -EPERM;
145 :
146 : return 0;
147 :
148 20 : out:
149 20 : set_failure_reason_callback(c, FR_DATA_CORRUPTED);
150 20 : ubifs_scan_destroy(sleb);
151 20 : return -EUCLEAN;
152 :
153 0 : out_dump:
154 0 : set_failure_reason_callback(c, FR_DATA_CORRUPTED);
155 0 : ubifs_err(c, "unexpected node type %d master LEB %d:%d",
156 : snod->type, lnum, snod->offs);
157 0 : ubifs_scan_destroy(sleb);
158 0 : return -EINVAL;
159 : }
160 :
161 : /**
162 : * validate_master - validate master node.
163 : * @c: UBIFS file-system description object
164 : *
165 : * This function validates data which was read from master node. Returns zero
166 : * if the data is all right and %-EINVAL if not.
167 : */
168 2283 : static int validate_master(const struct ubifs_info *c)
169 : {
170 2283 : unsigned int reason = FR_DATA_CORRUPTED;
171 : long long main_sz;
172 : int err;
173 :
174 2283 : if (c->max_sqnum >= SQNUM_WATERMARK) {
175 : err = 1;
176 : goto out;
177 : }
178 :
179 2283 : if (c->cmt_no >= c->max_sqnum) {
180 : err = 2;
181 : goto out;
182 : }
183 :
184 2283 : if (c->highest_inum >= INUM_WATERMARK) {
185 : err = 3;
186 : goto out;
187 : }
188 :
189 4548 : if (c->lhead_lnum < UBIFS_LOG_LNUM ||
190 4548 : c->lhead_lnum >= UBIFS_LOG_LNUM + c->log_lebs ||
191 6822 : c->lhead_offs < 0 || c->lhead_offs >= c->leb_size ||
192 2274 : c->lhead_offs & (c->min_io_size - 1)) {
193 : err = 4;
194 : goto out;
195 : }
196 :
197 4548 : if (c->zroot.lnum >= c->leb_cnt || c->zroot.lnum < c->main_first ||
198 4548 : c->zroot.offs >= c->leb_size || c->zroot.offs & 7) {
199 : err = 5;
200 : goto out;
201 : }
202 :
203 4548 : if (c->zroot.len < c->ranges[UBIFS_IDX_NODE].min_len ||
204 2274 : c->zroot.len > c->ranges[UBIFS_IDX_NODE].max_len) {
205 : err = 6;
206 : goto out;
207 : }
208 :
209 2274 : if (c->gc_lnum >= c->leb_cnt || c->gc_lnum < c->main_first) {
210 : err = 7;
211 : goto out;
212 : }
213 :
214 4548 : if (c->ihead_lnum >= c->leb_cnt || c->ihead_lnum < c->main_first ||
215 4548 : c->ihead_offs % c->min_io_size || c->ihead_offs < 0 ||
216 2274 : c->ihead_offs > c->leb_size || c->ihead_offs & 7) {
217 : err = 8;
218 : goto out;
219 : }
220 :
221 2274 : main_sz = (long long)c->main_lebs * c->leb_size;
222 2274 : if (c->bi.old_idx_sz & 7 || c->bi.old_idx_sz >= main_sz) {
223 : err = 9;
224 : goto out;
225 : }
226 :
227 4539 : if (c->lpt_lnum < c->lpt_first || c->lpt_lnum > c->lpt_last ||
228 4530 : c->lpt_offs < 0 || c->lpt_offs + c->nnode_sz > c->leb_size) {
229 : err = 10;
230 : goto out;
231 : }
232 :
233 4530 : if (c->nhead_lnum < c->lpt_first || c->nhead_lnum > c->lpt_last ||
234 4530 : c->nhead_offs < 0 || c->nhead_offs % c->min_io_size ||
235 : c->nhead_offs > c->leb_size) {
236 : err = 11;
237 : goto out;
238 : }
239 :
240 4530 : if (c->ltab_lnum < c->lpt_first || c->ltab_lnum > c->lpt_last ||
241 4530 : c->ltab_offs < 0 ||
242 2265 : c->ltab_offs + c->ltab_sz > c->leb_size) {
243 : err = 12;
244 : goto out;
245 : }
246 :
247 2265 : if (c->big_lpt && (c->lsave_lnum < c->lpt_first ||
248 48 : c->lsave_lnum > c->lpt_last || c->lsave_offs < 0 ||
249 24 : c->lsave_offs + c->lsave_sz > c->leb_size)) {
250 : err = 13;
251 : goto out;
252 : }
253 :
254 2265 : if (c->lscan_lnum < c->main_first || c->lscan_lnum >= c->leb_cnt) {
255 : err = 14;
256 : goto out;
257 : }
258 :
259 2265 : if (c->lst.empty_lebs < 0 || c->lst.empty_lebs > c->main_lebs - 2) {
260 : reason = FR_LPT_INCORRECT;
261 : err = 15;
262 : goto out;
263 : }
264 :
265 2265 : if (c->lst.idx_lebs < 0 || c->lst.idx_lebs > c->main_lebs - 1) {
266 : reason = FR_LPT_INCORRECT;
267 : err = 16;
268 : goto out;
269 : }
270 :
271 4527 : if (c->lst.total_free < 0 || c->lst.total_free > main_sz ||
272 2262 : c->lst.total_free & 7) {
273 : reason = FR_LPT_INCORRECT;
274 : err = 17;
275 : goto out;
276 : }
277 :
278 2262 : if (c->lst.total_dirty < 0 || (c->lst.total_dirty & 7)) {
279 : reason = FR_LPT_INCORRECT;
280 : err = 18;
281 : goto out;
282 : }
283 :
284 2259 : if (c->lst.total_used < 0 || (c->lst.total_used & 7)) {
285 : reason = FR_LPT_INCORRECT;
286 : err = 19;
287 : goto out;
288 : }
289 :
290 2259 : if (c->lst.total_free + c->lst.total_dirty +
291 : c->lst.total_used > main_sz) {
292 : reason = FR_LPT_INCORRECT;
293 : err = 20;
294 : goto out;
295 : }
296 :
297 4518 : if (c->lst.total_dead + c->lst.total_dark +
298 2259 : c->lst.total_used + c->bi.old_idx_sz > main_sz) {
299 : reason = FR_LPT_INCORRECT;
300 : err = 21;
301 : goto out;
302 : }
303 :
304 2256 : if (c->lst.total_dead < 0 ||
305 2256 : c->lst.total_dead > c->lst.total_free + c->lst.total_dirty ||
306 2256 : c->lst.total_dead & 7) {
307 : reason = FR_LPT_INCORRECT;
308 : err = 22;
309 : goto out;
310 : }
311 :
312 2256 : if (c->lst.total_dark < 0 ||
313 2256 : c->lst.total_dark > c->lst.total_free + c->lst.total_dirty ||
314 2256 : c->lst.total_dark & 7) {
315 : reason = FR_LPT_INCORRECT;
316 : err = 23;
317 : goto out;
318 : }
319 :
320 : return 0;
321 :
322 27 : out:
323 27 : set_failure_reason_callback(c, reason);
324 27 : ubifs_err(c, "bad master node at offset %d error %d", c->mst_offs, err);
325 27 : ubifs_dump_node(c, c->mst_node, c->mst_node_alsz);
326 27 : err = -EINVAL;
327 27 : if (can_ignore_failure_callback(c, reason)) {
328 : clear_failure_reason_callback(c);
329 : err = 0;
330 : }
331 : return err;
332 : }
333 :
334 : /**
335 : * ubifs_read_master - read master node.
336 : * @c: UBIFS file-system description object
337 : *
338 : * This function finds and reads the master node during file-system mount. If
339 : * the flash is empty, it creates default master node as well. Returns zero in
340 : * case of success and a negative error code in case of failure.
341 : */
342 2284 : int ubifs_read_master(struct ubifs_info *c)
343 : {
344 : int err, old_leb_cnt;
345 :
346 4568 : c->mst_node = kzalloc(c->mst_node_alsz, GFP_KERNEL);
347 2284 : if (!c->mst_node)
348 : return -ENOMEM;
349 :
350 2284 : err = scan_for_master(c);
351 2284 : if (err) {
352 29 : if (err == -EUCLEAN) {
353 29 : clear_failure_reason_callback(c);
354 29 : err = ubifs_recover_master_node(c);
355 : }
356 29 : if (err)
357 : /*
358 : * Note, we do not free 'c->mst_node' here because the
359 : * unmount routine will take care of this.
360 : */
361 : return err;
362 : }
363 :
364 : /* Make sure that the recovery flag is clear */
365 2283 : c->mst_node->flags &= cpu_to_le32(~UBIFS_MST_RCVRY);
366 :
367 2283 : c->max_sqnum = le64_to_cpu(c->mst_node->ch.sqnum);
368 2283 : c->highest_inum = le64_to_cpu(c->mst_node->highest_inum);
369 2283 : c->cmt_no = le64_to_cpu(c->mst_node->cmt_no);
370 2283 : c->zroot.lnum = le32_to_cpu(c->mst_node->root_lnum);
371 2283 : c->zroot.offs = le32_to_cpu(c->mst_node->root_offs);
372 2283 : c->zroot.len = le32_to_cpu(c->mst_node->root_len);
373 2283 : c->lhead_lnum = le32_to_cpu(c->mst_node->log_lnum);
374 2283 : c->gc_lnum = le32_to_cpu(c->mst_node->gc_lnum);
375 2283 : c->ihead_lnum = le32_to_cpu(c->mst_node->ihead_lnum);
376 2283 : c->ihead_offs = le32_to_cpu(c->mst_node->ihead_offs);
377 2283 : c->bi.old_idx_sz = le64_to_cpu(c->mst_node->index_size);
378 2283 : c->lpt_lnum = le32_to_cpu(c->mst_node->lpt_lnum);
379 2283 : c->lpt_offs = le32_to_cpu(c->mst_node->lpt_offs);
380 2283 : c->nhead_lnum = le32_to_cpu(c->mst_node->nhead_lnum);
381 2283 : c->nhead_offs = le32_to_cpu(c->mst_node->nhead_offs);
382 2283 : c->ltab_lnum = le32_to_cpu(c->mst_node->ltab_lnum);
383 2283 : c->ltab_offs = le32_to_cpu(c->mst_node->ltab_offs);
384 2283 : c->lsave_lnum = le32_to_cpu(c->mst_node->lsave_lnum);
385 2283 : c->lsave_offs = le32_to_cpu(c->mst_node->lsave_offs);
386 2283 : c->lscan_lnum = le32_to_cpu(c->mst_node->lscan_lnum);
387 2283 : c->lst.empty_lebs = le32_to_cpu(c->mst_node->empty_lebs);
388 2283 : c->lst.idx_lebs = le32_to_cpu(c->mst_node->idx_lebs);
389 2283 : old_leb_cnt = le32_to_cpu(c->mst_node->leb_cnt);
390 2283 : c->lst.total_free = le64_to_cpu(c->mst_node->total_free);
391 2283 : c->lst.total_dirty = le64_to_cpu(c->mst_node->total_dirty);
392 2283 : c->lst.total_used = le64_to_cpu(c->mst_node->total_used);
393 2283 : c->lst.total_dead = le64_to_cpu(c->mst_node->total_dead);
394 2283 : c->lst.total_dark = le64_to_cpu(c->mst_node->total_dark);
395 :
396 4566 : ubifs_copy_hash(c, c->mst_node->hash_root_idx, c->zroot.hash);
397 :
398 2283 : c->calc_idx_sz = c->bi.old_idx_sz;
399 :
400 2283 : if (c->mst_node->flags & cpu_to_le32(UBIFS_MST_NO_ORPHS))
401 2219 : c->no_orphs = 1;
402 :
403 2283 : if (old_leb_cnt != c->leb_cnt) {
404 : /* The file system has been resized */
405 264 : int growth = c->leb_cnt - old_leb_cnt;
406 :
407 264 : if (c->leb_cnt < old_leb_cnt ||
408 : c->leb_cnt < UBIFS_MIN_LEB_CNT) {
409 0 : set_failure_reason_callback(c, FR_DATA_CORRUPTED);
410 0 : ubifs_err(c, "bad leb_cnt on master node");
411 0 : ubifs_dump_node(c, c->mst_node, c->mst_node_alsz);
412 0 : return -EINVAL;
413 : }
414 :
415 264 : dbg_mnt("Auto resizing (master) from %d LEBs to %d LEBs",
416 : old_leb_cnt, c->leb_cnt);
417 264 : c->lst.empty_lebs += growth;
418 264 : c->lst.total_free += growth * (long long)c->leb_size;
419 264 : c->lst.total_dark += growth * (long long)c->dark_wm;
420 :
421 : /*
422 : * Reflect changes back onto the master node. N.B. the master
423 : * node gets written immediately whenever mounting (or
424 : * remounting) in read-write mode, so we do not need to write it
425 : * here.
426 : */
427 264 : c->mst_node->leb_cnt = cpu_to_le32(c->leb_cnt);
428 264 : c->mst_node->empty_lebs = cpu_to_le32(c->lst.empty_lebs);
429 264 : c->mst_node->total_free = cpu_to_le64(c->lst.total_free);
430 264 : c->mst_node->total_dark = cpu_to_le64(c->lst.total_dark);
431 : }
432 :
433 2283 : err = validate_master(c);
434 2283 : if (err)
435 : return err;
436 :
437 2265 : err = dbg_old_index_check_init(c, &c->zroot);
438 :
439 2265 : return err;
440 : }
441 :
442 : /**
443 : * ubifs_write_master - write master node.
444 : * @c: UBIFS file-system description object
445 : *
446 : * This function writes the master node. Returns zero in case of success and a
447 : * negative error code in case of failure. The master node is written twice to
448 : * enable recovery.
449 : */
450 4498 : int ubifs_write_master(struct ubifs_info *c)
451 : {
452 : int err, lnum, offs, len;
453 :
454 4498 : ubifs_assert(c, !c->ro_media && !c->ro_mount);
455 4498 : if (c->ro_error)
456 : return -EROFS;
457 :
458 4498 : lnum = UBIFS_MST_LNUM;
459 4498 : offs = c->mst_offs + c->mst_node_alsz;
460 4498 : len = UBIFS_MST_NODE_SZ;
461 :
462 4498 : if (offs + UBIFS_MST_NODE_SZ > c->leb_size) {
463 42 : err = ubifs_leb_unmap(c, lnum);
464 42 : if (err)
465 : return err;
466 : offs = 0;
467 : }
468 :
469 4498 : c->mst_offs = offs;
470 4498 : c->mst_node->highest_inum = cpu_to_le64(c->highest_inum);
471 :
472 8996 : ubifs_copy_hash(c, c->zroot.hash, c->mst_node->hash_root_idx);
473 4498 : err = ubifs_write_node_hmac(c, c->mst_node, len, lnum, offs,
474 : offsetof(struct ubifs_mst_node, hmac));
475 4498 : if (err)
476 : return err;
477 :
478 4496 : lnum += 1;
479 :
480 4496 : if (offs == 0) {
481 42 : err = ubifs_leb_unmap(c, lnum);
482 42 : if (err)
483 : return err;
484 : }
485 4496 : err = ubifs_write_node_hmac(c, c->mst_node, len, lnum, offs,
486 : offsetof(struct ubifs_mst_node, hmac));
487 :
488 4496 : return err;
489 : }
|