diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_attr_leaf.c')
-rw-r--r-- | fs/xfs/libxfs/xfs_attr_leaf.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c index 6fc5425b1474..2652d00842d6 100644 --- a/fs/xfs/libxfs/xfs_attr_leaf.c +++ b/fs/xfs/libxfs/xfs_attr_leaf.c | |||
@@ -243,7 +243,7 @@ xfs_attr3_leaf_verify( | |||
243 | struct xfs_mount *mp = bp->b_target->bt_mount; | 243 | struct xfs_mount *mp = bp->b_target->bt_mount; |
244 | struct xfs_attr_leafblock *leaf = bp->b_addr; | 244 | struct xfs_attr_leafblock *leaf = bp->b_addr; |
245 | struct xfs_attr_leaf_entry *entries; | 245 | struct xfs_attr_leaf_entry *entries; |
246 | uint16_t end; | 246 | uint32_t end; /* must be 32bit - see below */ |
247 | int i; | 247 | int i; |
248 | 248 | ||
249 | xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf); | 249 | xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf); |
@@ -293,6 +293,11 @@ xfs_attr3_leaf_verify( | |||
293 | /* | 293 | /* |
294 | * Quickly check the freemap information. Attribute data has to be | 294 | * Quickly check the freemap information. Attribute data has to be |
295 | * aligned to 4-byte boundaries, and likewise for the free space. | 295 | * aligned to 4-byte boundaries, and likewise for the free space. |
296 | * | ||
297 | * Note that for 64k block size filesystems, the freemap entries cannot | ||
298 | * overflow as they are only be16 fields. However, when checking end | ||
299 | * pointer of the freemap, we have to be careful to detect overflows and | ||
300 | * so use uint32_t for those checks. | ||
296 | */ | 301 | */ |
297 | for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { | 302 | for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { |
298 | if (ichdr.freemap[i].base > mp->m_attr_geo->blksize) | 303 | if (ichdr.freemap[i].base > mp->m_attr_geo->blksize) |
@@ -303,7 +308,9 @@ xfs_attr3_leaf_verify( | |||
303 | return __this_address; | 308 | return __this_address; |
304 | if (ichdr.freemap[i].size & 0x3) | 309 | if (ichdr.freemap[i].size & 0x3) |
305 | return __this_address; | 310 | return __this_address; |
306 | end = ichdr.freemap[i].base + ichdr.freemap[i].size; | 311 | |
312 | /* be care of 16 bit overflows here */ | ||
313 | end = (uint32_t)ichdr.freemap[i].base + ichdr.freemap[i].size; | ||
307 | if (end < ichdr.freemap[i].base) | 314 | if (end < ichdr.freemap[i].base) |
308 | return __this_address; | 315 | return __this_address; |
309 | if (end > mp->m_attr_geo->blksize) | 316 | if (end > mp->m_attr_geo->blksize) |