ubifs: Pass node length in all node dumping callers
authorZhihao Cheng <chengzhihao1@huawei.com>
Tue, 16 Jun 2020 07:11:44 +0000 (15:11 +0800)
committerRichard Weinberger <richard@nod.at>
Sun, 13 Dec 2020 21:12:32 +0000 (22:12 +0100)
Function ubifs_dump_node() has been modified to avoid memory oob
accessing while dumping node, node length (corresponding to the
size of allocated memory for node) should be passed into all node
dumping callers.

Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
15 files changed:
fs/ubifs/commit.c
fs/ubifs/debug.c
fs/ubifs/file.c
fs/ubifs/io.c
fs/ubifs/journal.c
fs/ubifs/master.c
fs/ubifs/orphan.c
fs/ubifs/recovery.c
fs/ubifs/replay.c
fs/ubifs/sb.c
fs/ubifs/scan.c
fs/ubifs/super.c
fs/ubifs/tnc.c
fs/ubifs/tnc_misc.c
fs/ubifs/ubifs.h

index b5cdac9b0368dca93491f0331695f475032b1db4..c4fc1047fc0797f492a8f0cdf596f9f2215fd907 100644 (file)
@@ -701,13 +701,13 @@ out:
 
 out_dump:
        ubifs_err(c, "dumping index node (iip=%d)", i->iip);
-       ubifs_dump_node(c, idx);
+       ubifs_dump_node(c, idx, ubifs_idx_node_sz(c, c->fanout));
        list_del(&i->list);
        kfree(i);
        if (!list_empty(&list)) {
                i = list_entry(list.prev, struct idx_node, list);
                ubifs_err(c, "dumping parent index node");
-               ubifs_dump_node(c, &i->idx);
+               ubifs_dump_node(c, &i->idx, ubifs_idx_node_sz(c, c->fanout));
        }
 out_free:
        while (!list_empty(&list)) {
index 707741353bc968a10f62357a207e66691d3a7d9c..5d78056067a26b5847196d32995aadc8de65451a 100644 (file)
@@ -871,7 +871,7 @@ void ubifs_dump_leb(const struct ubifs_info *c, int lnum)
                cond_resched();
                pr_err("Dumping node at LEB %d:%d len %d\n", lnum,
                       snod->offs, snod->len);
-               ubifs_dump_node(c, snod->node);
+               ubifs_dump_node(c, snod->node, c->leb_size - snod->offs);
        }
 
        pr_err("(pid %d) finish dumping LEB %d\n", current->pid, lnum);
@@ -1249,7 +1249,7 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1,
                ubifs_err(c, "but it should have key %s according to tnc",
                          dbg_snprintf_key(c, &zbr1->key, key_buf,
                                           DBG_KEY_BUF_LEN));
-               ubifs_dump_node(c, dent1);
+               ubifs_dump_node(c, dent1, UBIFS_MAX_DENT_NODE_SZ);
                goto out_free;
        }
 
@@ -1261,7 +1261,7 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1,
                ubifs_err(c, "but it should have key %s according to tnc",
                          dbg_snprintf_key(c, &zbr2->key, key_buf,
                                           DBG_KEY_BUF_LEN));
-               ubifs_dump_node(c, dent2);
+               ubifs_dump_node(c, dent2, UBIFS_MAX_DENT_NODE_SZ);
                goto out_free;
        }
 
@@ -1280,9 +1280,9 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1,
                          dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
 
        ubifs_msg(c, "first node at %d:%d\n", zbr1->lnum, zbr1->offs);
-       ubifs_dump_node(c, dent1);
+       ubifs_dump_node(c, dent1, UBIFS_MAX_DENT_NODE_SZ);
        ubifs_msg(c, "second node at %d:%d\n", zbr2->lnum, zbr2->offs);
-       ubifs_dump_node(c, dent2);
+       ubifs_dump_node(c, dent2, UBIFS_MAX_DENT_NODE_SZ);
 
 out_free:
        kfree(dent2);
@@ -2147,7 +2147,7 @@ out:
 
 out_dump:
        ubifs_msg(c, "dump of node at LEB %d:%d", zbr->lnum, zbr->offs);
-       ubifs_dump_node(c, node);
+       ubifs_dump_node(c, node, zbr->len);
 out_free:
        kfree(node);
        return err;
@@ -2280,7 +2280,7 @@ out_dump:
 
        ubifs_msg(c, "dump of the inode %lu sitting in LEB %d:%d",
                  (unsigned long)fscki->inum, zbr->lnum, zbr->offs);
-       ubifs_dump_node(c, ino);
+       ubifs_dump_node(c, ino, zbr->len);
        kfree(ino);
        return -EINVAL;
 }
@@ -2351,12 +2351,12 @@ int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head)
 
                if (sa->type != UBIFS_DATA_NODE) {
                        ubifs_err(c, "bad node type %d", sa->type);
-                       ubifs_dump_node(c, sa->node);
+                       ubifs_dump_node(c, sa->node, c->leb_size - sa->offs);
                        return -EINVAL;
                }
                if (sb->type != UBIFS_DATA_NODE) {
                        ubifs_err(c, "bad node type %d", sb->type);
-                       ubifs_dump_node(c, sb->node);
+                       ubifs_dump_node(c, sb->node, c->leb_size - sb->offs);
                        return -EINVAL;
                }
 
@@ -2387,8 +2387,8 @@ int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head)
        return 0;
 
 error_dump:
-       ubifs_dump_node(c, sa->node);
-       ubifs_dump_node(c, sb->node);
+       ubifs_dump_node(c, sa->node, c->leb_size - sa->offs);
+       ubifs_dump_node(c, sb->node, c->leb_size - sb->offs);
        return -EINVAL;
 }
 
@@ -2419,13 +2419,13 @@ int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head)
                if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE &&
                    sa->type != UBIFS_XENT_NODE) {
                        ubifs_err(c, "bad node type %d", sa->type);
-                       ubifs_dump_node(c, sa->node);
+                       ubifs_dump_node(c, sa->node, c->leb_size - sa->offs);
                        return -EINVAL;
                }
                if (sb->type != UBIFS_INO_NODE && sb->type != UBIFS_DENT_NODE &&
                    sb->type != UBIFS_XENT_NODE) {
                        ubifs_err(c, "bad node type %d", sb->type);
-                       ubifs_dump_node(c, sb->node);
+                       ubifs_dump_node(c, sb->node, c->leb_size - sb->offs);
                        return -EINVAL;
                }
 
@@ -2475,9 +2475,9 @@ int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head)
 
 error_dump:
        ubifs_msg(c, "dumping first node");
-       ubifs_dump_node(c, sa->node);
+       ubifs_dump_node(c, sa->node, c->leb_size - sa->offs);
        ubifs_msg(c, "dumping second node");
-       ubifs_dump_node(c, sb->node);
+       ubifs_dump_node(c, sb->node, c->leb_size - sb->offs);
        return -EINVAL;
 }
 
index cacb970bcf48b7ddbf624bb949f8a8d83b3d5d72..2bc7780d2963c8f709d130a4626326fd03f045d0 100644 (file)
@@ -92,7 +92,7 @@ static int read_block(struct inode *inode, void *addr, unsigned int block,
 dump:
        ubifs_err(c, "bad data node (block %u, inode %lu)",
                  block, inode->i_ino);
-       ubifs_dump_node(c, dn);
+       ubifs_dump_node(c, dn, UBIFS_MAX_DATA_NODE_SZ);
        return -EINVAL;
 }
 
index be50cb598a389a8842366e34db77016e6df0cd7b..00b61dba62b70ffbf638fb8bac41b99920745c0c 100644 (file)
@@ -198,6 +198,7 @@ int ubifs_is_mapped(const struct ubifs_info *c, int lnum)
  * ubifs_check_node - check node.
  * @c: UBIFS file-system description object
  * @buf: node to check
+ * @len: node length
  * @lnum: logical eraseblock number
  * @offs: offset within the logical eraseblock
  * @quiet: print no messages
@@ -222,8 +223,8 @@ int ubifs_is_mapped(const struct ubifs_info *c, int lnum)
  * This function returns zero in case of success and %-EUCLEAN in case of bad
  * CRC or magic.
  */
-int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
-                    int offs, int quiet, int must_chk_crc)
+int ubifs_check_node(const struct ubifs_info *c, const void *buf, int len,
+                    int lnum, int offs, int quiet, int must_chk_crc)
 {
        int err = -EINVAL, type, node_len;
        uint32_t crc, node_crc, magic;
@@ -281,7 +282,7 @@ out_len:
 out:
        if (!quiet) {
                ubifs_err(c, "bad node at LEB %d:%d", lnum, offs);
-               ubifs_dump_node(c, buf);
+               ubifs_dump_node(c, buf, len);
                dump_stack();
        }
        return err;
@@ -718,7 +719,7 @@ out_timers:
 int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
 {
        struct ubifs_info *c = wbuf->c;
-       int err, written, n, aligned_len = ALIGN(len, 8);
+       int err, n, written = 0, aligned_len = ALIGN(len, 8);
 
        dbg_io("%d bytes (%s) to jhead %s wbuf at LEB %d:%d", len,
               dbg_ntype(((struct ubifs_ch *)buf)->node_type),
@@ -785,8 +786,6 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
                goto exit;
        }
 
-       written = 0;
-
        if (wbuf->used) {
                /*
                 * The node is large enough and does not fit entirely within
@@ -887,7 +886,7 @@ exit:
 out:
        ubifs_err(c, "cannot write %d bytes to LEB %d:%d, error %d",
                  len, wbuf->lnum, wbuf->offs, err);
-       ubifs_dump_node(c, buf);
+       ubifs_dump_node(c, buf, written + len);
        dump_stack();
        ubifs_dump_leb(c, wbuf->lnum);
        return err;
@@ -930,7 +929,7 @@ int ubifs_write_node_hmac(struct ubifs_info *c, void *buf, int len, int lnum,
 
        err = ubifs_leb_write(c, lnum, buf, offs, buf_len);
        if (err)
-               ubifs_dump_node(c, buf);
+               ubifs_dump_node(c, buf, len);
 
        return err;
 }
@@ -1013,7 +1012,7 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
                goto out;
        }
 
-       err = ubifs_check_node(c, buf, lnum, offs, 0, 0);
+       err = ubifs_check_node(c, buf, len, lnum, offs, 0, 0);
        if (err) {
                ubifs_err(c, "expected node type %d", type);
                return err;
@@ -1029,7 +1028,7 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
 
 out:
        ubifs_err(c, "bad node at LEB %d:%d", lnum, offs);
-       ubifs_dump_node(c, buf);
+       ubifs_dump_node(c, buf, len);
        dump_stack();
        return -EINVAL;
 }
@@ -1069,7 +1068,7 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
                goto out;
        }
 
-       err = ubifs_check_node(c, buf, lnum, offs, 0, 0);
+       err = ubifs_check_node(c, buf, len, lnum, offs, 0, 0);
        if (err) {
                ubifs_errc(c, "expected node type %d", type);
                return err;
@@ -1087,7 +1086,7 @@ out:
        ubifs_errc(c, "bad node at LEB %d:%d, LEB mapping status %d", lnum,
                   offs, ubi_is_mapped(c->ubi, lnum));
        if (!c->probing) {
-               ubifs_dump_node(c, buf);
+               ubifs_dump_node(c, buf, len);
                dump_stack();
        }
        return -EINVAL;
index 091c2ad8f21113ac7f04f9b8d89e59b57027880d..03410ae0813a74b2faaf1599c3c5a10a1ad58e16 100644 (file)
@@ -1559,7 +1559,8 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode,
                        if (dn_len <= 0 || dn_len > UBIFS_BLOCK_SIZE) {
                                ubifs_err(c, "bad data node (block %u, inode %lu)",
                                          blk, inode->i_ino);
-                               ubifs_dump_node(c, dn);
+                               ubifs_dump_node(c, dn, sz - UBIFS_INO_NODE_SZ -
+                                               UBIFS_TRUN_NODE_SZ);
                                goto out_free;
                        }
 
index 911d0555b9f2b1be56fb05f983940e281b636f18..0df9a3dd0aaa2063dfbb75177b5518a51cbd831e 100644 (file)
@@ -314,7 +314,7 @@ static int validate_master(const struct ubifs_info *c)
 
 out:
        ubifs_err(c, "bad master node at offset %d error %d", c->mst_offs, err);
-       ubifs_dump_node(c, c->mst_node);
+       ubifs_dump_node(c, c->mst_node, c->mst_node_alsz);
        return -EINVAL;
 }
 
@@ -392,7 +392,7 @@ int ubifs_read_master(struct ubifs_info *c)
                if (c->leb_cnt < old_leb_cnt ||
                    c->leb_cnt < UBIFS_MIN_LEB_CNT) {
                        ubifs_err(c, "bad leb_cnt on master node");
-                       ubifs_dump_node(c, c->mst_node);
+                       ubifs_dump_node(c, c->mst_node, c->mst_node_alsz);
                        return -EINVAL;
                }
 
index 0fb61956146da6efe34315eb97c08d7cf45fae0e..4909321d84cf83ccd84bb0a5396dbbf1a6a24b71 100644 (file)
@@ -646,7 +646,8 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
                if (snod->type != UBIFS_ORPH_NODE) {
                        ubifs_err(c, "invalid node type %d in orphan area at %d:%d",
                                  snod->type, sleb->lnum, snod->offs);
-                       ubifs_dump_node(c, snod->node);
+                       ubifs_dump_node(c, snod->node,
+                                       c->leb_size - snod->offs);
                        err = -EINVAL;
                        goto out_free;
                }
@@ -674,7 +675,8 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
                        if (!first) {
                                ubifs_err(c, "out of order commit number %llu in orphan node at %d:%d",
                                          cmt_no, sleb->lnum, snod->offs);
-                               ubifs_dump_node(c, snod->node);
+                               ubifs_dump_node(c, snod->node,
+                                               c->leb_size - snod->offs);
                                err = -EINVAL;
                                goto out_free;
                        }
index f116f7b3f9e5fa5761efc7c1cc375c2dd18ffd21..f0d51dd21c9e13d5ba13e29f3caa703bc84e8b61 100644 (file)
@@ -352,11 +352,11 @@ out_free:
        ubifs_err(c, "failed to recover master node");
        if (mst1) {
                ubifs_err(c, "dumping first master node");
-               ubifs_dump_node(c, mst1);
+               ubifs_dump_node(c, mst1, c->leb_size - ((void *)mst1 - buf1));
        }
        if (mst2) {
                ubifs_err(c, "dumping second master node");
-               ubifs_dump_node(c, mst2);
+               ubifs_dump_node(c, mst2, c->leb_size - ((void *)mst2 - buf2));
        }
        vfree(buf2);
        vfree(buf1);
@@ -469,7 +469,7 @@ static int no_more_nodes(const struct ubifs_info *c, void *buf, int len,
         * The area after the common header size is not empty, so the common
         * header must be intact. Check it.
         */
-       if (ubifs_check_node(c, buf, lnum, offs, 1, 0) != -EUCLEAN) {
+       if (ubifs_check_node(c, buf, len, lnum, offs, 1, 0) != -EUCLEAN) {
                dbg_rcvry("unexpected bad common header at %d:%d", lnum, offs);
                return 0;
        }
index d0bbb30781b325e3e1c1848f8602e3cec0ae8357..79801c9a5b8742432dbf9ed08c0353d1375bdeb5 100644 (file)
@@ -827,7 +827,7 @@ out:
 
 out_dump:
        ubifs_err(c, "bad node is at LEB %d:%d", lnum, snod->offs);
-       ubifs_dump_node(c, snod->node);
+       ubifs_dump_node(c, snod->node, c->leb_size - snod->offs);
        ubifs_scan_destroy(sleb);
        return -EINVAL;
 }
@@ -1123,7 +1123,7 @@ out:
 out_dump:
        ubifs_err(c, "log error detected while replaying the log at LEB %d:%d",
                  lnum, offs + snod->offs);
-       ubifs_dump_node(c, snod->node);
+       ubifs_dump_node(c, snod->node, c->leb_size - snod->offs);
        ubifs_scan_destroy(sleb);
        return -EINVAL;
 }
index c0d3e4008d23460de8f2dfe60f67a6065cc2d4ac..c160f718c28822e2c91f4b3e4bf12e408af64275 100644 (file)
@@ -503,7 +503,7 @@ static int validate_sb(struct ubifs_info *c, struct ubifs_sb_node *sup)
 
 failed:
        ubifs_err(c, "bad superblock, error %d", err);
-       ubifs_dump_node(c, sup);
+       ubifs_dump_node(c, sup, ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size));
        return -EINVAL;
 }
 
index c69cdb5e65bcede44ade118bbb7134009e7d0314..84a9157dcc32ca2b8df1bbe14cd3eb8dd051da36 100644 (file)
@@ -76,7 +76,7 @@ int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum,
        dbg_scan("scanning %s at LEB %d:%d",
                 dbg_ntype(ch->node_type), lnum, offs);
 
-       if (ubifs_check_node(c, buf, lnum, offs, quiet, 1))
+       if (ubifs_check_node(c, buf, len, lnum, offs, quiet, 1))
                return SCANNED_A_CORRUPT_NODE;
 
        if (ch->node_type == UBIFS_PAD_NODE) {
@@ -90,7 +90,7 @@ int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum,
                        if (!quiet) {
                                ubifs_err(c, "bad pad node at LEB %d:%d",
                                          lnum, offs);
-                               ubifs_dump_node(c, pad);
+                               ubifs_dump_node(c, pad, len);
                        }
                        return SCANNED_A_BAD_PAD_NODE;
                }
index 77dea673851b8e20973940b8099b1cdd8a44e2f1..138b9426c6c18abc0f9a8e215b03487f88f006d9 100644 (file)
@@ -253,7 +253,7 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
 
 out_invalid:
        ubifs_err(c, "inode %lu validation failed, error %d", inode->i_ino, err);
-       ubifs_dump_node(c, ino);
+       ubifs_dump_node(c, ino, UBIFS_MAX_INO_NODE_SZ);
        ubifs_dump_inode(c, inode);
        err = -EINVAL;
 out_ino:
index c90b1c7c6819ebe384d8f5e5c4c2289ba4187107..488f3da7a6c6ceef0e81a6323605249422c0b5af 100644 (file)
@@ -316,7 +316,7 @@ static int lnc_add(struct ubifs_info *c, struct ubifs_zbranch *zbr,
        err = ubifs_validate_entry(c, dent);
        if (err) {
                dump_stack();
-               ubifs_dump_node(c, dent);
+               ubifs_dump_node(c, dent, zbr->len);
                return err;
        }
 
@@ -349,7 +349,7 @@ static int lnc_add_directly(struct ubifs_info *c, struct ubifs_zbranch *zbr,
        err = ubifs_validate_entry(c, node);
        if (err) {
                dump_stack();
-               ubifs_dump_node(c, node);
+               ubifs_dump_node(c, node, zbr->len);
                return err;
        }
 
@@ -1699,7 +1699,7 @@ static int validate_data_node(struct ubifs_info *c, void *buf,
                goto out_err;
        }
 
-       err = ubifs_check_node(c, buf, zbr->lnum, zbr->offs, 0, 0);
+       err = ubifs_check_node(c, buf, zbr->len, zbr->lnum, zbr->offs, 0, 0);
        if (err) {
                ubifs_err(c, "expected node type %d", UBIFS_DATA_NODE);
                goto out;
@@ -1733,7 +1733,7 @@ out_err:
        err = -EINVAL;
 out:
        ubifs_err(c, "bad node at LEB %d:%d", zbr->lnum, zbr->offs);
-       ubifs_dump_node(c, buf);
+       ubifs_dump_node(c, buf, zbr->len);
        dump_stack();
        return err;
 }
index fcb451ef88b8cb95603dee1ed71745a21ee7bed4..4d686e34e64d99feb54a3ab351fbf31fd6a5a476 100644 (file)
@@ -390,7 +390,7 @@ static int read_znode(struct ubifs_info *c, struct ubifs_zbranch *zzbr,
 
 out_dump:
        ubifs_err(c, "bad indexing node at LEB %d:%d, error %d", lnum, offs, err);
-       ubifs_dump_node(c, idx);
+       ubifs_dump_node(c, idx, c->max_idx_node_sz);
        kfree(idx);
        return -EINVAL;
 }
@@ -488,7 +488,7 @@ int ubifs_tnc_read_node(struct ubifs_info *c, struct ubifs_zbranch *zbr,
                          zbr->lnum, zbr->offs);
                dbg_tnck(key, "looked for key ");
                dbg_tnck(&key1, "but found node's key ");
-               ubifs_dump_node(c, node);
+               ubifs_dump_node(c, node, zbr->len);
                return -EINVAL;
        }
 
index f99450844ac32630cd71c4a65a5bf27d466fc84b..fc2cdde3b5499f65ec7682ae68e844fdec0dabcf 100644 (file)
@@ -1719,8 +1719,8 @@ int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum,
                     int offs);
 int ubifs_write_node_hmac(struct ubifs_info *c, void *buf, int len, int lnum,
                          int offs, int hmac_offs);
-int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
-                    int offs, int quiet, int must_chk_crc);
+int ubifs_check_node(const struct ubifs_info *c, const void *buf, int len,
+                    int lnum, int offs, int quiet, int must_chk_crc);
 void ubifs_init_node(struct ubifs_info *c, void *buf, int len, int pad);
 void ubifs_crc_node(struct ubifs_info *c, void *buf, int len);
 void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad);