diff --git a/fsck/fsck.c b/fsck/fsck.c index 324c3d5..f0ee9f9 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -832,7 +832,7 @@ check_next: le16_to_cpu(node_blk->i.i_inline_xattr_size); if (!inline_size || - inline_size > MAX_INLINE_XATTR_SIZE) { + inline_size > MAX_INLINE_XATTR_SIZE(&node_blk->i)) { ASSERT_MSG("[0x%x] wrong inline_xattr_size:%u", nid, inline_size); if (c.fix_on) { diff --git a/fsck/xattr.c b/fsck/xattr.c index 8e66873..20f2c0a 100644 --- a/fsck/xattr.c +++ b/fsck/xattr.c @@ -151,7 +151,7 @@ int f2fs_setxattr(struct f2fs_sb_info *sbi, nid_t ino, int index, const char *na len = strlen(name); - if (len > F2FS_NAME_LEN || size > MAX_VALUE_LEN) + if (len > F2FS_NAME_LEN) return -ERANGE; if (ino < 3) @@ -166,6 +166,12 @@ 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); + if (size > MAX_VALUE_LEN(&inode->i)) { + MSG(0, "Size %d exceeds max value len %d.\n", size, MAX_VALUE_LEN(&inode->i)); + free(inode); + return -ERANGE; + } + base_addr = read_all_xattrs(sbi, inode); ASSERT(base_addr); diff --git a/fsck/xattr.h b/fsck/xattr.h index 22ea35c..8491407 100644 --- a/fsck/xattr.h +++ b/fsck/xattr.h @@ -135,13 +135,14 @@ static inline int f2fs_acl_count(int size) #define MIN_OFFSET XATTR_ALIGN(F2FS_BLKSIZE - \ sizeof(struct node_footer) - sizeof(__u32)) -#define MAX_VALUE_LEN (MIN_OFFSET - \ +#define MAX_XATTR_BLOCK_SIZE (F2FS_BLKSIZE - sizeof(struct node_footer)) + +#define MAX_XATTR_SIZE(inode) (XATTR_ALIGN((MAX_INLINE_XATTR_SIZE(inode)) + \ + (MAX_XATTR_BLOCK_SIZE))) + +#define MAX_VALUE_LEN(inode) (MAX_XATTR_SIZE(inode) - \ sizeof(struct f2fs_xattr_header) - \ sizeof(struct f2fs_xattr_entry)) -#define MAX_INLINE_XATTR_SIZE \ - (DEF_ADDRS_PER_INODE - \ - F2FS_TOTAL_EXTRA_ATTR_SIZE / sizeof(__le32) - \ - DEF_INLINE_RESERVED_SIZE - \ - MIN_INLINE_DENTRY_SIZE / sizeof(__le32)) +#define MAX_INLINE_XATTR_SIZE(inode) (inline_xattr_size(inode)) #endif