hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/ubifs/replay.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: Adrian Hunter
208 * Artem Bityutskiy (Битюцкий Артём)
....@@ -34,6 +22,8 @@
3422
3523 #include "ubifs.h"
3624 #include <linux/list_sort.h>
25
+#include <crypto/hash.h>
26
+#include <crypto/algapi.h>
3727
3828 /**
3929 * struct replay_entry - replay list entry.
....@@ -56,6 +46,7 @@
5646 int lnum;
5747 int offs;
5848 int len;
49
+ u8 hash[UBIFS_HASH_ARR_SZ];
5950 unsigned int deletion:1;
6051 unsigned long long sqnum;
6152 struct list_head list;
....@@ -261,7 +252,7 @@
261252 err = ubifs_tnc_remove_nm(c, &r->key, &r->nm);
262253 else
263254 err = ubifs_tnc_add_nm(c, &r->key, r->lnum, r->offs,
264
- r->len, &r->nm);
255
+ r->len, r->hash, &r->nm);
265256 } else {
266257 if (r->deletion)
267258 switch (key_type(c, &r->key)) {
....@@ -286,7 +277,7 @@
286277 }
287278 else
288279 err = ubifs_tnc_add(c, &r->key, r->lnum, r->offs,
289
- r->len);
280
+ r->len, r->hash);
290281 if (err)
291282 return err;
292283
....@@ -390,9 +381,9 @@
390381 * in case of success and a negative error code in case of failure.
391382 */
392383 static int insert_node(struct ubifs_info *c, int lnum, int offs, int len,
393
- union ubifs_key *key, unsigned long long sqnum,
394
- int deletion, int *used, loff_t old_size,
395
- loff_t new_size)
384
+ const u8 *hash, union ubifs_key *key,
385
+ unsigned long long sqnum, int deletion, int *used,
386
+ loff_t old_size, loff_t new_size)
396387 {
397388 struct replay_entry *r;
398389
....@@ -410,6 +401,7 @@
410401 r->lnum = lnum;
411402 r->offs = offs;
412403 r->len = len;
404
+ ubifs_copy_hash(c, hash, r->hash);
413405 r->deletion = !!deletion;
414406 r->sqnum = sqnum;
415407 key_copy(c, key, &r->key);
....@@ -438,8 +430,9 @@
438430 * negative error code in case of failure.
439431 */
440432 static int insert_dent(struct ubifs_info *c, int lnum, int offs, int len,
441
- union ubifs_key *key, const char *name, int nlen,
442
- unsigned long long sqnum, int deletion, int *used)
433
+ const u8 *hash, union ubifs_key *key,
434
+ const char *name, int nlen, unsigned long long sqnum,
435
+ int deletion, int *used)
443436 {
444437 struct replay_entry *r;
445438 char *nbuf;
....@@ -463,6 +456,7 @@
463456 r->lnum = lnum;
464457 r->offs = offs;
465458 r->len = len;
459
+ ubifs_copy_hash(c, hash, r->hash);
466460 r->deletion = !!deletion;
467461 r->sqnum = sqnum;
468462 key_copy(c, key, &r->key);
....@@ -565,6 +559,101 @@
565559 return data == 0xFFFFFFFF;
566560 }
567561
562
+/* authenticate_sleb_hash is split out for stack usage */
563
+static int noinline_for_stack
564
+authenticate_sleb_hash(struct ubifs_info *c,
565
+ struct shash_desc *log_hash, u8 *hash)
566
+{
567
+ SHASH_DESC_ON_STACK(hash_desc, c->hash_tfm);
568
+
569
+ hash_desc->tfm = c->hash_tfm;
570
+
571
+ ubifs_shash_copy_state(c, log_hash, hash_desc);
572
+ return crypto_shash_final(hash_desc, hash);
573
+}
574
+
575
+/**
576
+ * authenticate_sleb - authenticate one scan LEB
577
+ * @c: UBIFS file-system description object
578
+ * @sleb: the scan LEB to authenticate
579
+ * @log_hash:
580
+ * @is_last: if true, this is is the last LEB
581
+ *
582
+ * This function iterates over the buds of a single LEB authenticating all buds
583
+ * with the authentication nodes on this LEB. Authentication nodes are written
584
+ * after some buds and contain a HMAC covering the authentication node itself
585
+ * and the buds between the last authentication node and the current
586
+ * authentication node. It can happen that the last buds cannot be authenticated
587
+ * because a powercut happened when some nodes were written but not the
588
+ * corresponding authentication node. This function returns the number of nodes
589
+ * that could be authenticated or a negative error code.
590
+ */
591
+static int authenticate_sleb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
592
+ struct shash_desc *log_hash, int is_last)
593
+{
594
+ int n_not_auth = 0;
595
+ struct ubifs_scan_node *snod;
596
+ int n_nodes = 0;
597
+ int err;
598
+ u8 hash[UBIFS_HASH_ARR_SZ];
599
+ u8 hmac[UBIFS_HMAC_ARR_SZ];
600
+
601
+ if (!ubifs_authenticated(c))
602
+ return sleb->nodes_cnt;
603
+
604
+ list_for_each_entry(snod, &sleb->nodes, list) {
605
+
606
+ n_nodes++;
607
+
608
+ if (snod->type == UBIFS_AUTH_NODE) {
609
+ struct ubifs_auth_node *auth = snod->node;
610
+
611
+ err = authenticate_sleb_hash(c, log_hash, hash);
612
+ if (err)
613
+ goto out;
614
+
615
+ err = crypto_shash_tfm_digest(c->hmac_tfm, hash,
616
+ c->hash_len, hmac);
617
+ if (err)
618
+ goto out;
619
+
620
+ err = ubifs_check_hmac(c, auth->hmac, hmac);
621
+ if (err) {
622
+ err = -EPERM;
623
+ goto out;
624
+ }
625
+ n_not_auth = 0;
626
+ } else {
627
+ err = crypto_shash_update(log_hash, snod->node,
628
+ snod->len);
629
+ if (err)
630
+ goto out;
631
+ n_not_auth++;
632
+ }
633
+ }
634
+
635
+ /*
636
+ * A powercut can happen when some nodes were written, but not yet
637
+ * the corresponding authentication node. This may only happen on
638
+ * the last bud though.
639
+ */
640
+ if (n_not_auth) {
641
+ if (is_last) {
642
+ dbg_mnt("%d unauthenticated nodes found on LEB %d, Ignoring them",
643
+ n_not_auth, sleb->lnum);
644
+ err = 0;
645
+ } else {
646
+ dbg_mnt("%d unauthenticated nodes found on non-last LEB %d",
647
+ n_not_auth, sleb->lnum);
648
+ err = -EPERM;
649
+ }
650
+ } else {
651
+ err = 0;
652
+ }
653
+out:
654
+ return err ? err : n_nodes - n_not_auth;
655
+}
656
+
568657 /**
569658 * replay_bud - replay a bud logical eraseblock.
570659 * @c: UBIFS file-system description object
....@@ -578,6 +667,7 @@
578667 {
579668 int is_last = is_last_bud(c, b->bud);
580669 int err = 0, used = 0, lnum = b->bud->lnum, offs = b->bud->start;
670
+ int n_nodes, n = 0;
581671 struct ubifs_scan_leb *sleb;
582672 struct ubifs_scan_node *snod;
583673
....@@ -596,6 +686,15 @@
596686 sleb = ubifs_scan(c, lnum, offs, c->sbuf, 0);
597687 if (IS_ERR(sleb))
598688 return PTR_ERR(sleb);
689
+
690
+ n_nodes = authenticate_sleb(c, sleb, b->bud->log_hash, is_last);
691
+ if (n_nodes < 0) {
692
+ err = n_nodes;
693
+ goto out;
694
+ }
695
+
696
+ ubifs_shash_copy_state(c, b->bud->log_hash,
697
+ c->jheads[b->bud->jhead].log_hash);
599698
600699 /*
601700 * The bud does not have to start from offset zero - the beginning of
....@@ -620,6 +719,7 @@
620719 */
621720
622721 list_for_each_entry(snod, &sleb->nodes, list) {
722
+ u8 hash[UBIFS_HASH_ARR_SZ];
623723 int deletion = 0;
624724
625725 cond_resched();
....@@ -628,6 +728,8 @@
628728 ubifs_err(c, "file system's life ended");
629729 goto out_dump;
630730 }
731
+
732
+ ubifs_node_calc_hash(c, snod->node, hash);
631733
632734 if (snod->sqnum > c->max_sqnum)
633735 c->max_sqnum = snod->sqnum;
....@@ -640,7 +742,7 @@
640742
641743 if (le32_to_cpu(ino->nlink) == 0)
642744 deletion = 1;
643
- err = insert_node(c, lnum, snod->offs, snod->len,
745
+ err = insert_node(c, lnum, snod->offs, snod->len, hash,
644746 &snod->key, snod->sqnum, deletion,
645747 &used, 0, new_size);
646748 break;
....@@ -652,7 +754,7 @@
652754 key_block(c, &snod->key) *
653755 UBIFS_BLOCK_SIZE;
654756
655
- err = insert_node(c, lnum, snod->offs, snod->len,
757
+ err = insert_node(c, lnum, snod->offs, snod->len, hash,
656758 &snod->key, snod->sqnum, deletion,
657759 &used, 0, new_size);
658760 break;
....@@ -666,7 +768,7 @@
666768 if (err)
667769 goto out_dump;
668770
669
- err = insert_dent(c, lnum, snod->offs, snod->len,
771
+ err = insert_dent(c, lnum, snod->offs, snod->len, hash,
670772 &snod->key, dent->name,
671773 le16_to_cpu(dent->nlen), snod->sqnum,
672774 !le64_to_cpu(dent->inum), &used);
....@@ -692,11 +794,13 @@
692794 * functions which expect nodes to have keys.
693795 */
694796 trun_key_init(c, &key, le32_to_cpu(trun->inum));
695
- err = insert_node(c, lnum, snod->offs, snod->len,
797
+ err = insert_node(c, lnum, snod->offs, snod->len, hash,
696798 &key, snod->sqnum, 1, &used,
697799 old_size, new_size);
698800 break;
699801 }
802
+ case UBIFS_AUTH_NODE:
803
+ break;
700804 default:
701805 ubifs_err(c, "unexpected node type %d in bud LEB %d:%d",
702806 snod->type, lnum, snod->offs);
....@@ -705,6 +809,10 @@
705809 }
706810 if (err)
707811 goto out;
812
+
813
+ n++;
814
+ if (n == n_nodes)
815
+ break;
708816 }
709817
710818 ubifs_assert(c, ubifs_search_bud(c, lnum));
....@@ -783,6 +891,7 @@
783891 {
784892 struct ubifs_bud *bud;
785893 struct bud_entry *b;
894
+ int err;
786895
787896 dbg_mnt("add replay bud LEB %d:%d, head %d", lnum, offs, jhead);
788897
....@@ -792,13 +901,21 @@
792901
793902 b = kmalloc(sizeof(struct bud_entry), GFP_KERNEL);
794903 if (!b) {
795
- kfree(bud);
796
- return -ENOMEM;
904
+ err = -ENOMEM;
905
+ goto out;
797906 }
798907
799908 bud->lnum = lnum;
800909 bud->start = offs;
801910 bud->jhead = jhead;
911
+ bud->log_hash = ubifs_hash_get_desc(c);
912
+ if (IS_ERR(bud->log_hash)) {
913
+ err = PTR_ERR(bud->log_hash);
914
+ goto out;
915
+ }
916
+
917
+ ubifs_shash_copy_state(c, c->log_hash, bud->log_hash);
918
+
802919 ubifs_add_bud(c, bud);
803920
804921 b->bud = bud;
....@@ -806,14 +923,17 @@
806923 list_add_tail(&b->list, &c->replay_buds);
807924
808925 return 0;
926
+out:
927
+ kfree(bud);
928
+ kfree(b);
929
+
930
+ return err;
809931 }
810932
811933 /**
812934 * validate_ref - validate a reference node.
813935 * @c: UBIFS file-system description object
814936 * @ref: the reference node to validate
815
- * @ref_lnum: LEB number of the reference node
816
- * @ref_offs: reference node offset
817937 *
818938 * This function returns %1 if a bud reference already exists for the LEB. %0 is
819939 * returned if the reference node is new, otherwise %-EINVAL is returned if
....@@ -911,6 +1031,14 @@
9111031
9121032 c->cs_sqnum = le64_to_cpu(node->ch.sqnum);
9131033 dbg_mnt("commit start sqnum %llu", c->cs_sqnum);
1034
+
1035
+ err = ubifs_shash_init(c, c->log_hash);
1036
+ if (err)
1037
+ goto out;
1038
+
1039
+ err = ubifs_shash_update(c, c->log_hash, node, UBIFS_CS_NODE_SZ);
1040
+ if (err < 0)
1041
+ goto out;
9141042 }
9151043
9161044 if (snod->sqnum < c->cs_sqnum) {
....@@ -958,6 +1086,11 @@
9581086 if (err)
9591087 goto out_dump;
9601088
1089
+ err = ubifs_shash_update(c, c->log_hash, ref,
1090
+ UBIFS_REF_NODE_SZ);
1091
+ if (err)
1092
+ goto out;
1093
+
9611094 err = add_replay_bud(c, le32_to_cpu(ref->lnum),
9621095 le32_to_cpu(ref->offs),
9631096 le32_to_cpu(ref->jhead),