Skip to content

Commit

Permalink
f2fs-tools: fix corrupted xattr entry
Browse files Browse the repository at this point in the history
Detect and fix a corrupted xattr entry.

Signed-off-by: Daeho Jeong <daehojeong@google.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
  • Loading branch information
Daeho Jeong authored and Jaegeuk Kim committed Oct 26, 2023
1 parent 0f503e4 commit c9009e0
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 7 deletions.
2 changes: 1 addition & 1 deletion fsck/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ static void dump_xattr(struct f2fs_sb_info *sbi, struct f2fs_node *node_blk)
char xattr_name[F2FS_NAME_LEN] = {0};
int ret;

xattr = read_all_xattrs(sbi, node_blk);
xattr = read_all_xattrs(sbi, node_blk, true);
if (!xattr)
return;

Expand Down
40 changes: 40 additions & 0 deletions fsck/fsck.c
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,43 @@ void fsck_reada_all_direct_node_blocks(struct f2fs_sb_info *sbi,
}
}

int chk_extended_attributes(struct f2fs_sb_info *sbi, u32 nid,
struct f2fs_node *inode)
{
void *xattr;
void *last_base_addr;
struct f2fs_xattr_entry *ent;
__u32 xattr_size = XATTR_SIZE(&inode->i);

if (xattr_size == 0)
return 0;

xattr = read_all_xattrs(sbi, inode, false);
ASSERT(xattr);

last_base_addr = (void *)xattr + xattr_size;

list_for_each_xattr(ent, xattr) {
if ((void *)(ent) + sizeof(__u32) > last_base_addr ||
(void *)XATTR_NEXT_ENTRY(ent) > last_base_addr) {
ASSERT_MSG("[0x%x] last xattr entry (offset: %lx) "
"crosses the boundary",
nid, (long int)((void *)ent - xattr));
if (c.fix_on) {
memset(ent, 0,
(char *)last_base_addr - (char *)ent);
write_all_xattrs(sbi, inode, xattr_size, xattr);
FIX_MSG("[0x%x] nullify wrong xattr entries",
nid);
return 1;
}
break;
}
}

return 0;
}

/* start with valid nid and blkaddr */
void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
enum FILE_TYPE ftype, struct f2fs_node *node_blk,
Expand Down Expand Up @@ -1008,6 +1045,9 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
}
}

if (chk_extended_attributes(sbi, nid, node_blk))
need_fix = 1;

if ((node_blk->i.i_inline & F2FS_INLINE_DATA)) {
unsigned int inline_size = MAX_INLINE_DATA(node_blk);
if (cur_qtype != -1)
Expand Down
4 changes: 3 additions & 1 deletion fsck/fsck.h
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,8 @@ struct hardlink_cache_entry *f2fs_search_hardlink(struct f2fs_sb_info *sbi,
struct dentry *de);

/* xattr.c */
void *read_all_xattrs(struct f2fs_sb_info *, struct f2fs_node *);
void *read_all_xattrs(struct f2fs_sb_info *, struct f2fs_node *, bool);
void write_all_xattrs(struct f2fs_sb_info *sbi,
struct f2fs_node *inode, __u32 hsize, void *txattr_addr);

#endif /* _FSCK_H_ */
2 changes: 1 addition & 1 deletion fsck/mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ void print_inode_info(struct f2fs_sb_info *sbi,
DISP_u32(F2FS_INODE_NIDS(inode), i_nid[3]); /* indirect */
DISP_u32(F2FS_INODE_NIDS(inode), i_nid[4]); /* double indirect */

xattr_addr = read_all_xattrs(sbi, node);
xattr_addr = read_all_xattrs(sbi, node, true);
if (!xattr_addr)
goto out;

Expand Down
9 changes: 5 additions & 4 deletions fsck/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@
#include "node.h"
#include "xattr.h"

void *read_all_xattrs(struct f2fs_sb_info *sbi, struct f2fs_node *inode)
void *read_all_xattrs(struct f2fs_sb_info *sbi, struct f2fs_node *inode,
bool sanity_check)
{
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 (c.func == FSCK && xnid) {
if (c.func == FSCK && xnid && sanity_check) {
if (fsck_sanity_check_nid(sbi, xnid, F2FS_FT_XATTR, TYPE_XATTR))
return NULL;
}
Expand Down Expand Up @@ -78,7 +79,7 @@ static struct f2fs_xattr_entry *__find_xattr(void *base_addr,
return entry;
}

static void write_all_xattrs(struct f2fs_sb_info *sbi,
void write_all_xattrs(struct f2fs_sb_info *sbi,
struct f2fs_node *inode, __u32 hsize, void *txattr_addr)
{
void *xattr_addr;
Expand Down Expand Up @@ -165,7 +166,7 @@ int f2fs_setxattr(struct f2fs_sb_info *sbi, nid_t ino, int index, const char *na
ret = dev_read_block(inode, ni.blk_addr);
ASSERT(ret >= 0);

base_addr = read_all_xattrs(sbi, inode);
base_addr = read_all_xattrs(sbi, inode, true);
ASSERT(base_addr);

last_base_addr = (void *)base_addr + XATTR_SIZE(&inode->i);
Expand Down

0 comments on commit c9009e0

Please sign in to comment.