Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * This file is part of UBIFS.
0004  *
0005  * Copyright (C) 2006-2008 Nokia Corporation.
0006  *
0007  * Authors: Artem Bityutskiy (Битюцкий Артём)
0008  *          Adrian Hunter
0009  */
0010 
0011 /* This file implements reading and writing the master node */
0012 
0013 #include "ubifs.h"
0014 
0015 /**
0016  * ubifs_compare_master_node - compare two UBIFS master nodes
0017  * @c: UBIFS file-system description object
0018  * @m1: the first node
0019  * @m2: the second node
0020  *
0021  * This function compares two UBIFS master nodes. Returns 0 if they are equal
0022  * and nonzero if not.
0023  */
0024 int ubifs_compare_master_node(struct ubifs_info *c, void *m1, void *m2)
0025 {
0026     int ret;
0027     int behind;
0028     int hmac_offs = offsetof(struct ubifs_mst_node, hmac);
0029 
0030     /*
0031      * Do not compare the common node header since the sequence number and
0032      * hence the CRC are different.
0033      */
0034     ret = memcmp(m1 + UBIFS_CH_SZ, m2 + UBIFS_CH_SZ,
0035              hmac_offs - UBIFS_CH_SZ);
0036     if (ret)
0037         return ret;
0038 
0039     /*
0040      * Do not compare the embedded HMAC as well which also must be different
0041      * due to the different common node header.
0042      */
0043     behind = hmac_offs + UBIFS_MAX_HMAC_LEN;
0044 
0045     if (UBIFS_MST_NODE_SZ > behind)
0046         return memcmp(m1 + behind, m2 + behind, UBIFS_MST_NODE_SZ - behind);
0047 
0048     return 0;
0049 }
0050 
0051 /* mst_node_check_hash - Check hash of a master node
0052  * @c: UBIFS file-system description object
0053  * @mst: The master node
0054  * @expected: The expected hash of the master node
0055  *
0056  * This checks the hash of a master node against a given expected hash.
0057  * Note that we have two master nodes on a UBIFS image which have different
0058  * sequence numbers and consequently different CRCs. To be able to match
0059  * both master nodes we exclude the common node header containing the sequence
0060  * number and CRC from the hash.
0061  *
0062  * Returns 0 if the hashes are equal, a negative error code otherwise.
0063  */
0064 static int mst_node_check_hash(const struct ubifs_info *c,
0065                    const struct ubifs_mst_node *mst,
0066                    const u8 *expected)
0067 {
0068     u8 calc[UBIFS_MAX_HASH_LEN];
0069     const void *node = mst;
0070 
0071     crypto_shash_tfm_digest(c->hash_tfm, node + sizeof(struct ubifs_ch),
0072                 UBIFS_MST_NODE_SZ - sizeof(struct ubifs_ch),
0073                 calc);
0074 
0075     if (ubifs_check_hash(c, expected, calc))
0076         return -EPERM;
0077 
0078     return 0;
0079 }
0080 
0081 /**
0082  * scan_for_master - search the valid master node.
0083  * @c: UBIFS file-system description object
0084  *
0085  * This function scans the master node LEBs and search for the latest master
0086  * node. Returns zero in case of success, %-EUCLEAN if there master area is
0087  * corrupted and requires recovery, and a negative error code in case of
0088  * failure.
0089  */
0090 static int scan_for_master(struct ubifs_info *c)
0091 {
0092     struct ubifs_scan_leb *sleb;
0093     struct ubifs_scan_node *snod;
0094     int lnum, offs = 0, nodes_cnt, err;
0095 
0096     lnum = UBIFS_MST_LNUM;
0097 
0098     sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1);
0099     if (IS_ERR(sleb))
0100         return PTR_ERR(sleb);
0101     nodes_cnt = sleb->nodes_cnt;
0102     if (nodes_cnt > 0) {
0103         snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node,
0104                   list);
0105         if (snod->type != UBIFS_MST_NODE)
0106             goto out_dump;
0107         memcpy(c->mst_node, snod->node, snod->len);
0108         offs = snod->offs;
0109     }
0110     ubifs_scan_destroy(sleb);
0111 
0112     lnum += 1;
0113 
0114     sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1);
0115     if (IS_ERR(sleb))
0116         return PTR_ERR(sleb);
0117     if (sleb->nodes_cnt != nodes_cnt)
0118         goto out;
0119     if (!sleb->nodes_cnt)
0120         goto out;
0121     snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, list);
0122     if (snod->type != UBIFS_MST_NODE)
0123         goto out_dump;
0124     if (snod->offs != offs)
0125         goto out;
0126     if (ubifs_compare_master_node(c, c->mst_node, snod->node))
0127         goto out;
0128 
0129     c->mst_offs = offs;
0130     ubifs_scan_destroy(sleb);
0131 
0132     if (!ubifs_authenticated(c))
0133         return 0;
0134 
0135     if (ubifs_hmac_zero(c, c->mst_node->hmac)) {
0136         err = mst_node_check_hash(c, c->mst_node,
0137                       c->sup_node->hash_mst);
0138         if (err)
0139             ubifs_err(c, "Failed to verify master node hash");
0140     } else {
0141         err = ubifs_node_verify_hmac(c, c->mst_node,
0142                     sizeof(struct ubifs_mst_node),
0143                     offsetof(struct ubifs_mst_node, hmac));
0144         if (err)
0145             ubifs_err(c, "Failed to verify master node HMAC");
0146     }
0147 
0148     if (err)
0149         return -EPERM;
0150 
0151     return 0;
0152 
0153 out:
0154     ubifs_scan_destroy(sleb);
0155     return -EUCLEAN;
0156 
0157 out_dump:
0158     ubifs_err(c, "unexpected node type %d master LEB %d:%d",
0159           snod->type, lnum, snod->offs);
0160     ubifs_scan_destroy(sleb);
0161     return -EINVAL;
0162 }
0163 
0164 /**
0165  * validate_master - validate master node.
0166  * @c: UBIFS file-system description object
0167  *
0168  * This function validates data which was read from master node. Returns zero
0169  * if the data is all right and %-EINVAL if not.
0170  */
0171 static int validate_master(const struct ubifs_info *c)
0172 {
0173     long long main_sz;
0174     int err;
0175 
0176     if (c->max_sqnum >= SQNUM_WATERMARK) {
0177         err = 1;
0178         goto out;
0179     }
0180 
0181     if (c->cmt_no >= c->max_sqnum) {
0182         err = 2;
0183         goto out;
0184     }
0185 
0186     if (c->highest_inum >= INUM_WATERMARK) {
0187         err = 3;
0188         goto out;
0189     }
0190 
0191     if (c->lhead_lnum < UBIFS_LOG_LNUM ||
0192         c->lhead_lnum >= UBIFS_LOG_LNUM + c->log_lebs ||
0193         c->lhead_offs < 0 || c->lhead_offs >= c->leb_size ||
0194         c->lhead_offs & (c->min_io_size - 1)) {
0195         err = 4;
0196         goto out;
0197     }
0198 
0199     if (c->zroot.lnum >= c->leb_cnt || c->zroot.lnum < c->main_first ||
0200         c->zroot.offs >= c->leb_size || c->zroot.offs & 7) {
0201         err = 5;
0202         goto out;
0203     }
0204 
0205     if (c->zroot.len < c->ranges[UBIFS_IDX_NODE].min_len ||
0206         c->zroot.len > c->ranges[UBIFS_IDX_NODE].max_len) {
0207         err = 6;
0208         goto out;
0209     }
0210 
0211     if (c->gc_lnum >= c->leb_cnt || c->gc_lnum < c->main_first) {
0212         err = 7;
0213         goto out;
0214     }
0215 
0216     if (c->ihead_lnum >= c->leb_cnt || c->ihead_lnum < c->main_first ||
0217         c->ihead_offs % c->min_io_size || c->ihead_offs < 0 ||
0218         c->ihead_offs > c->leb_size || c->ihead_offs & 7) {
0219         err = 8;
0220         goto out;
0221     }
0222 
0223     main_sz = (long long)c->main_lebs * c->leb_size;
0224     if (c->bi.old_idx_sz & 7 || c->bi.old_idx_sz >= main_sz) {
0225         err = 9;
0226         goto out;
0227     }
0228 
0229     if (c->lpt_lnum < c->lpt_first || c->lpt_lnum > c->lpt_last ||
0230         c->lpt_offs < 0 || c->lpt_offs + c->nnode_sz > c->leb_size) {
0231         err = 10;
0232         goto out;
0233     }
0234 
0235     if (c->nhead_lnum < c->lpt_first || c->nhead_lnum > c->lpt_last ||
0236         c->nhead_offs < 0 || c->nhead_offs % c->min_io_size ||
0237         c->nhead_offs > c->leb_size) {
0238         err = 11;
0239         goto out;
0240     }
0241 
0242     if (c->ltab_lnum < c->lpt_first || c->ltab_lnum > c->lpt_last ||
0243         c->ltab_offs < 0 ||
0244         c->ltab_offs + c->ltab_sz > c->leb_size) {
0245         err = 12;
0246         goto out;
0247     }
0248 
0249     if (c->big_lpt && (c->lsave_lnum < c->lpt_first ||
0250         c->lsave_lnum > c->lpt_last || c->lsave_offs < 0 ||
0251         c->lsave_offs + c->lsave_sz > c->leb_size)) {
0252         err = 13;
0253         goto out;
0254     }
0255 
0256     if (c->lscan_lnum < c->main_first || c->lscan_lnum >= c->leb_cnt) {
0257         err = 14;
0258         goto out;
0259     }
0260 
0261     if (c->lst.empty_lebs < 0 || c->lst.empty_lebs > c->main_lebs - 2) {
0262         err = 15;
0263         goto out;
0264     }
0265 
0266     if (c->lst.idx_lebs < 0 || c->lst.idx_lebs > c->main_lebs - 1) {
0267         err = 16;
0268         goto out;
0269     }
0270 
0271     if (c->lst.total_free < 0 || c->lst.total_free > main_sz ||
0272         c->lst.total_free & 7) {
0273         err = 17;
0274         goto out;
0275     }
0276 
0277     if (c->lst.total_dirty < 0 || (c->lst.total_dirty & 7)) {
0278         err = 18;
0279         goto out;
0280     }
0281 
0282     if (c->lst.total_used < 0 || (c->lst.total_used & 7)) {
0283         err = 19;
0284         goto out;
0285     }
0286 
0287     if (c->lst.total_free + c->lst.total_dirty +
0288         c->lst.total_used > main_sz) {
0289         err = 20;
0290         goto out;
0291     }
0292 
0293     if (c->lst.total_dead + c->lst.total_dark +
0294         c->lst.total_used + c->bi.old_idx_sz > main_sz) {
0295         err = 21;
0296         goto out;
0297     }
0298 
0299     if (c->lst.total_dead < 0 ||
0300         c->lst.total_dead > c->lst.total_free + c->lst.total_dirty ||
0301         c->lst.total_dead & 7) {
0302         err = 22;
0303         goto out;
0304     }
0305 
0306     if (c->lst.total_dark < 0 ||
0307         c->lst.total_dark > c->lst.total_free + c->lst.total_dirty ||
0308         c->lst.total_dark & 7) {
0309         err = 23;
0310         goto out;
0311     }
0312 
0313     return 0;
0314 
0315 out:
0316     ubifs_err(c, "bad master node at offset %d error %d", c->mst_offs, err);
0317     ubifs_dump_node(c, c->mst_node, c->mst_node_alsz);
0318     return -EINVAL;
0319 }
0320 
0321 /**
0322  * ubifs_read_master - read master node.
0323  * @c: UBIFS file-system description object
0324  *
0325  * This function finds and reads the master node during file-system mount. If
0326  * the flash is empty, it creates default master node as well. Returns zero in
0327  * case of success and a negative error code in case of failure.
0328  */
0329 int ubifs_read_master(struct ubifs_info *c)
0330 {
0331     int err, old_leb_cnt;
0332 
0333     c->mst_node = kzalloc(c->mst_node_alsz, GFP_KERNEL);
0334     if (!c->mst_node)
0335         return -ENOMEM;
0336 
0337     err = scan_for_master(c);
0338     if (err) {
0339         if (err == -EUCLEAN)
0340             err = ubifs_recover_master_node(c);
0341         if (err)
0342             /*
0343              * Note, we do not free 'c->mst_node' here because the
0344              * unmount routine will take care of this.
0345              */
0346             return err;
0347     }
0348 
0349     /* Make sure that the recovery flag is clear */
0350     c->mst_node->flags &= cpu_to_le32(~UBIFS_MST_RCVRY);
0351 
0352     c->max_sqnum       = le64_to_cpu(c->mst_node->ch.sqnum);
0353     c->highest_inum    = le64_to_cpu(c->mst_node->highest_inum);
0354     c->cmt_no          = le64_to_cpu(c->mst_node->cmt_no);
0355     c->zroot.lnum      = le32_to_cpu(c->mst_node->root_lnum);
0356     c->zroot.offs      = le32_to_cpu(c->mst_node->root_offs);
0357     c->zroot.len       = le32_to_cpu(c->mst_node->root_len);
0358     c->lhead_lnum      = le32_to_cpu(c->mst_node->log_lnum);
0359     c->gc_lnum         = le32_to_cpu(c->mst_node->gc_lnum);
0360     c->ihead_lnum      = le32_to_cpu(c->mst_node->ihead_lnum);
0361     c->ihead_offs      = le32_to_cpu(c->mst_node->ihead_offs);
0362     c->bi.old_idx_sz   = le64_to_cpu(c->mst_node->index_size);
0363     c->lpt_lnum        = le32_to_cpu(c->mst_node->lpt_lnum);
0364     c->lpt_offs        = le32_to_cpu(c->mst_node->lpt_offs);
0365     c->nhead_lnum      = le32_to_cpu(c->mst_node->nhead_lnum);
0366     c->nhead_offs      = le32_to_cpu(c->mst_node->nhead_offs);
0367     c->ltab_lnum       = le32_to_cpu(c->mst_node->ltab_lnum);
0368     c->ltab_offs       = le32_to_cpu(c->mst_node->ltab_offs);
0369     c->lsave_lnum      = le32_to_cpu(c->mst_node->lsave_lnum);
0370     c->lsave_offs      = le32_to_cpu(c->mst_node->lsave_offs);
0371     c->lscan_lnum      = le32_to_cpu(c->mst_node->lscan_lnum);
0372     c->lst.empty_lebs  = le32_to_cpu(c->mst_node->empty_lebs);
0373     c->lst.idx_lebs    = le32_to_cpu(c->mst_node->idx_lebs);
0374     old_leb_cnt        = le32_to_cpu(c->mst_node->leb_cnt);
0375     c->lst.total_free  = le64_to_cpu(c->mst_node->total_free);
0376     c->lst.total_dirty = le64_to_cpu(c->mst_node->total_dirty);
0377     c->lst.total_used  = le64_to_cpu(c->mst_node->total_used);
0378     c->lst.total_dead  = le64_to_cpu(c->mst_node->total_dead);
0379     c->lst.total_dark  = le64_to_cpu(c->mst_node->total_dark);
0380 
0381     ubifs_copy_hash(c, c->mst_node->hash_root_idx, c->zroot.hash);
0382 
0383     c->calc_idx_sz = c->bi.old_idx_sz;
0384 
0385     if (c->mst_node->flags & cpu_to_le32(UBIFS_MST_NO_ORPHS))
0386         c->no_orphs = 1;
0387 
0388     if (old_leb_cnt != c->leb_cnt) {
0389         /* The file system has been resized */
0390         int growth = c->leb_cnt - old_leb_cnt;
0391 
0392         if (c->leb_cnt < old_leb_cnt ||
0393             c->leb_cnt < UBIFS_MIN_LEB_CNT) {
0394             ubifs_err(c, "bad leb_cnt on master node");
0395             ubifs_dump_node(c, c->mst_node, c->mst_node_alsz);
0396             return -EINVAL;
0397         }
0398 
0399         dbg_mnt("Auto resizing (master) from %d LEBs to %d LEBs",
0400             old_leb_cnt, c->leb_cnt);
0401         c->lst.empty_lebs += growth;
0402         c->lst.total_free += growth * (long long)c->leb_size;
0403         c->lst.total_dark += growth * (long long)c->dark_wm;
0404 
0405         /*
0406          * Reflect changes back onto the master node. N.B. the master
0407          * node gets written immediately whenever mounting (or
0408          * remounting) in read-write mode, so we do not need to write it
0409          * here.
0410          */
0411         c->mst_node->leb_cnt = cpu_to_le32(c->leb_cnt);
0412         c->mst_node->empty_lebs = cpu_to_le32(c->lst.empty_lebs);
0413         c->mst_node->total_free = cpu_to_le64(c->lst.total_free);
0414         c->mst_node->total_dark = cpu_to_le64(c->lst.total_dark);
0415     }
0416 
0417     err = validate_master(c);
0418     if (err)
0419         return err;
0420 
0421     err = dbg_old_index_check_init(c, &c->zroot);
0422 
0423     return err;
0424 }
0425 
0426 /**
0427  * ubifs_write_master - write master node.
0428  * @c: UBIFS file-system description object
0429  *
0430  * This function writes the master node. Returns zero in case of success and a
0431  * negative error code in case of failure. The master node is written twice to
0432  * enable recovery.
0433  */
0434 int ubifs_write_master(struct ubifs_info *c)
0435 {
0436     int err, lnum, offs, len;
0437 
0438     ubifs_assert(c, !c->ro_media && !c->ro_mount);
0439     if (c->ro_error)
0440         return -EROFS;
0441 
0442     lnum = UBIFS_MST_LNUM;
0443     offs = c->mst_offs + c->mst_node_alsz;
0444     len = UBIFS_MST_NODE_SZ;
0445 
0446     if (offs + UBIFS_MST_NODE_SZ > c->leb_size) {
0447         err = ubifs_leb_unmap(c, lnum);
0448         if (err)
0449             return err;
0450         offs = 0;
0451     }
0452 
0453     c->mst_offs = offs;
0454     c->mst_node->highest_inum = cpu_to_le64(c->highest_inum);
0455 
0456     ubifs_copy_hash(c, c->zroot.hash, c->mst_node->hash_root_idx);
0457     err = ubifs_write_node_hmac(c, c->mst_node, len, lnum, offs,
0458                     offsetof(struct ubifs_mst_node, hmac));
0459     if (err)
0460         return err;
0461 
0462     lnum += 1;
0463 
0464     if (offs == 0) {
0465         err = ubifs_leb_unmap(c, lnum);
0466         if (err)
0467             return err;
0468     }
0469     err = ubifs_write_node_hmac(c, c->mst_node, len, lnum, offs,
0470                     offsetof(struct ubifs_mst_node, hmac));
0471 
0472     return err;
0473 }