Skip to content

Commit

Permalink
ubifs: Pass node length in all node dumping callers
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Richard Weinberger <[email protected]>
  • Loading branch information
Zhihao Cheng authored and richardweinberger committed Dec 13, 2020
1 parent c8be097 commit a33e30a
Show file tree
Hide file tree
Showing 15 changed files with 54 additions and 52 deletions.
4 changes: 2 additions & 2 deletions fs/ubifs/commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -701,13 +701,13 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)

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)) {
Expand Down
30 changes: 15 additions & 15 deletions fs/ubifs/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand All @@ -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);
Expand Down Expand Up @@ -2147,7 +2147,7 @@ static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr,

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;
Expand Down Expand Up @@ -2280,7 +2280,7 @@ static int check_inodes(struct ubifs_info *c, struct fsck_data *fsckd)

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;
}
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion fs/ubifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
23 changes: 11 additions & 12 deletions fs/ubifs/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -281,7 +282,7 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
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;
Expand Down Expand Up @@ -718,7 +719,7 @@ int ubifs_bg_wbufs_sync(struct ubifs_info *c)
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),
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -887,7 +886,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -1087,7 +1086,7 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
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;
Expand Down
3 changes: 2 additions & 1 deletion fs/ubifs/journal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
4 changes: 2 additions & 2 deletions fs/ubifs/master.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down
6 changes: 4 additions & 2 deletions fs/ubifs/orphan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down
6 changes: 3 additions & 3 deletions fs/ubifs/recovery.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,11 +352,11 @@ int ubifs_recover_master_node(struct ubifs_info *c)
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);
Expand Down Expand Up @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions fs/ubifs/replay.c
Original file line number Diff line number Diff line change
Expand Up @@ -827,7 +827,7 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b)

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;
}
Expand Down Expand Up @@ -1123,7 +1123,7 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf)
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;
}
Expand Down
2 changes: 1 addition & 1 deletion fs/ubifs/sb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
4 changes: 2 additions & 2 deletions fs/ubifs/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion fs/ubifs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
8 changes: 4 additions & 4 deletions fs/ubifs/tnc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1733,7 +1733,7 @@ static int validate_data_node(struct ubifs_info *c, void *buf,
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;
}
Expand Down
Loading

0 comments on commit a33e30a

Please sign in to comment.