From 7a22451bc2b41eabf343c20512ad30bcdc7d3ba9 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 7 Apr 2020 18:01:07 +0800 Subject: [PATCH] fsck.f2fs: fix to check validation of i_xattr_nid Otherwise, fsck.f2fs will access invalid memory address as below: - fsck_verify - dump_node - dump_file - dump_inode_blk - dump_xattr - read_all_xattrs - get_node_info access &(F2FS_FSCK(sbi)->entries[nid]) Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fsck/dump.c | 2 ++ fsck/fsck.c | 8 ++++++++ fsck/fsck.h | 3 +++ fsck/mount.c | 8 +++++--- fsck/xattr.c | 20 ++++++++++++++++++-- 5 files changed, 36 insertions(+), 5 deletions(-) diff --git a/fsck/dump.c b/fsck/dump.c index 144c10e..001b7cb 100644 --- a/fsck/dump.c +++ b/fsck/dump.c @@ -309,6 +309,8 @@ static void dump_xattr(struct f2fs_sb_info *sbi, struct f2fs_node *node_blk) int ret; xattr = read_all_xattrs(sbi, node_blk); + if (!xattr) + return; list_for_each_xattr(ent, xattr) { char *name = strndup(ent->e_name, ent->e_name_len); diff --git a/fsck/fsck.c b/fsck/fsck.c index a08a8cb..0389146 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -487,6 +487,14 @@ static int sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid, return 0; } +int fsck_sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid, + struct f2fs_node *node_blk, + enum FILE_TYPE ftype, enum NODE_TYPE ntype, + struct node_info *ni) +{ + return sanity_check_nid(sbi, nid, node_blk, ftype, ntype, ni); +} + static int fsck_chk_xattr_blk(struct f2fs_sb_info *sbi, u32 ino, u32 x_nid, u32 *blk_cnt) { diff --git a/fsck/fsck.h b/fsck/fsck.h index c4432e8..2de6f62 100644 --- a/fsck/fsck.h +++ b/fsck/fsck.h @@ -144,6 +144,9 @@ static inline bool need_fsync_data_record(struct f2fs_sb_info *sbi) extern int fsck_chk_orphan_node(struct f2fs_sb_info *); extern int fsck_chk_quota_node(struct f2fs_sb_info *); extern int fsck_chk_quota_files(struct f2fs_sb_info *); +extern int fsck_sanity_check_nid(struct f2fs_sb_info *, u32, + struct f2fs_node *, enum FILE_TYPE, enum NODE_TYPE, + struct node_info *); extern int fsck_chk_node_blk(struct f2fs_sb_info *, struct f2fs_inode *, u32, enum FILE_TYPE, enum NODE_TYPE, u32 *, struct child_info *); diff --git a/fsck/mount.c b/fsck/mount.c index 4d16659..0aab071 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -257,10 +257,12 @@ void print_inode_info(struct f2fs_sb_info *sbi, DISP_u32(inode, i_nid[4]); /* double indirect */ xattr_addr = read_all_xattrs(sbi, node); - list_for_each_xattr(ent, xattr_addr) { - print_xattr_entry(ent); + if (xattr_addr) { + list_for_each_xattr(ent, xattr_addr) { + print_xattr_entry(ent); + } + free(xattr_addr); } - free(xattr_addr); printf("\n"); } diff --git a/fsck/xattr.c b/fsck/xattr.c index d5350e3..e9dcb52 100644 --- a/fsck/xattr.c +++ b/fsck/xattr.c @@ -22,6 +22,22 @@ void *read_all_xattrs(struct f2fs_sb_info *sbi, struct f2fs_node *inode) struct f2fs_xattr_header *header; void *txattr_addr; u64 inline_size = inline_xattr_size(&inode->i); + nid_t xnid = le32_to_cpu(inode->i.i_xattr_nid); + + if (xnid) { + struct f2fs_node *node_blk = NULL; + struct node_info ni; + int ret; + + node_blk = (struct f2fs_node *)calloc(BLOCK_SZ, 1); + ASSERT(node_blk != NULL); + + ret = fsck_sanity_check_nid(sbi, xnid, node_blk, + F2FS_FT_XATTR, TYPE_XATTR, &ni); + free(node_blk); + if (ret) + return NULL; + } txattr_addr = calloc(inline_size + BLOCK_SZ, 1); ASSERT(txattr_addr); @@ -30,11 +46,11 @@ void *read_all_xattrs(struct f2fs_sb_info *sbi, struct f2fs_node *inode) memcpy(txattr_addr, inline_xattr_addr(&inode->i), inline_size); /* Read from xattr node block. */ - if (inode->i.i_xattr_nid) { + if (xnid) { struct node_info ni; int ret; - get_node_info(sbi, le32_to_cpu(inode->i.i_xattr_nid), &ni); + get_node_info(sbi, xnid, &ni); ret = dev_read_block(txattr_addr + inline_size, ni.blk_addr); ASSERT(ret >= 0); } -- 2.7.4