xfs: AGI length should be bounds checked

Similar to the recent patch strengthening the AGF agf_length
verification, the AGI verifier does not check that the AGI length field
is within known good bounds. This isn't currently checked by runtime
kernel code, yet we assume in many places that it is correct and verify
other metadata against it.

Add length verification to the AGI verifier. Just like the AGF length
checking, the length of the AGI must be equal to the size of the AG
specified in the superblock, unless it is the last AG in the filesystem.
In that case, it must be less than or equal to sb->sb_agblocks and
greater than XFS_MIN_AG_BLOCKS, which is the smallest AG a growfs
operation will allow to exist.

There's only one place in the filesystem that actually uses agi_length,
but let's not leave it vulnerable to the same weird nonsense that
generates syzbot bugs, eh?

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>

+60 -39
+46 -26
fs/xfs/libxfs/xfs_alloc.c
··· 2957 } 2958 2959 /* 2960 * Verify the AGF is consistent. 2961 * 2962 * We do not verify the AGFL indexes in the AGF are fully consistent here ··· 3016 { 3017 struct xfs_mount *mp = bp->b_mount; 3018 struct xfs_agf *agf = bp->b_addr; 3019 uint32_t agf_length = be32_to_cpu(agf->agf_length); 3020 3021 if (xfs_has_crc(mp)) { ··· 3036 /* 3037 * Both agf_seqno and agf_length need to validated before anything else 3038 * block number related in the AGF or AGFL can be checked. 3039 - * 3040 - * During growfs operations, the perag is not fully initialised, 3041 - * so we can't use it for any useful checking. growfs ensures we can't 3042 - * use it by using uncached buffers that don't have the perag attached 3043 - * so we can detect and avoid this problem. 3044 */ 3045 - if (bp->b_pag && be32_to_cpu(agf->agf_seqno) != bp->b_pag->pag_agno) 3046 - return __this_address; 3047 - 3048 - /* 3049 - * Only the last AGF in the filesytsem is allowed to be shorter 3050 - * than the AG size recorded in the superblock. 3051 - */ 3052 - if (agf_length != mp->m_sb.sb_agblocks) { 3053 - /* 3054 - * During growfs, the new last AGF can get here before we 3055 - * have updated the superblock. Give it a pass on the seqno 3056 - * check. 3057 - */ 3058 - if (bp->b_pag && 3059 - be32_to_cpu(agf->agf_seqno) != mp->m_sb.sb_agcount - 1) 3060 - return __this_address; 3061 - if (agf_length < XFS_MIN_AG_BLOCKS) 3062 - return __this_address; 3063 - if (agf_length > mp->m_sb.sb_agblocks) 3064 - return __this_address; 3065 - } 3066 3067 if (be32_to_cpu(agf->agf_flfirst) >= xfs_agfl_size(mp)) 3068 return __this_address;
··· 2957 } 2958 2959 /* 2960 + * Check that this AGF/AGI header's sequence number and length matches the AG 2961 + * number and size in fsblocks. 2962 + */ 2963 + xfs_failaddr_t 2964 + xfs_validate_ag_length( 2965 + struct xfs_buf *bp, 2966 + uint32_t seqno, 2967 + uint32_t length) 2968 + { 2969 + struct xfs_mount *mp = bp->b_mount; 2970 + /* 2971 + * During growfs operations, the perag is not fully initialised, 2972 + * so we can't use it for any useful checking. growfs ensures we can't 2973 + * use it by using uncached buffers that don't have the perag attached 2974 + * so we can detect and avoid this problem. 2975 + */ 2976 + if (bp->b_pag && seqno != bp->b_pag->pag_agno) 2977 + return __this_address; 2978 + 2979 + /* 2980 + * Only the last AG in the filesystem is allowed to be shorter 2981 + * than the AG size recorded in the superblock. 2982 + */ 2983 + if (length != mp->m_sb.sb_agblocks) { 2984 + /* 2985 + * During growfs, the new last AG can get here before we 2986 + * have updated the superblock. Give it a pass on the seqno 2987 + * check. 2988 + */ 2989 + if (bp->b_pag && seqno != mp->m_sb.sb_agcount - 1) 2990 + return __this_address; 2991 + if (length < XFS_MIN_AG_BLOCKS) 2992 + return __this_address; 2993 + if (length > mp->m_sb.sb_agblocks) 2994 + return __this_address; 2995 + } 2996 + 2997 + return NULL; 2998 + } 2999 + 3000 + /* 3001 * Verify the AGF is consistent. 3002 * 3003 * We do not verify the AGFL indexes in the AGF are fully consistent here ··· 2975 { 2976 struct xfs_mount *mp = bp->b_mount; 2977 struct xfs_agf *agf = bp->b_addr; 2978 + xfs_failaddr_t fa; 2979 + uint32_t agf_seqno = be32_to_cpu(agf->agf_seqno); 2980 uint32_t agf_length = be32_to_cpu(agf->agf_length); 2981 2982 if (xfs_has_crc(mp)) { ··· 2993 /* 2994 * Both agf_seqno and agf_length need to validated before anything else 2995 * block number related in the AGF or AGFL can be checked. 2996 */ 2997 + fa = xfs_validate_ag_length(bp, agf_seqno, agf_length); 2998 + if (fa) 2999 + return fa; 3000 3001 if (be32_to_cpu(agf->agf_flfirst) >= xfs_agfl_size(mp)) 3002 return __this_address;
+3
fs/xfs/libxfs/xfs_alloc.h
··· 273 int __init xfs_extfree_intent_init_cache(void); 274 void xfs_extfree_intent_destroy_cache(void); 275 276 #endif /* __XFS_ALLOC_H__ */
··· 273 int __init xfs_extfree_intent_init_cache(void); 274 void xfs_extfree_intent_destroy_cache(void); 275 276 + xfs_failaddr_t xfs_validate_ag_length(struct xfs_buf *bp, uint32_t seqno, 277 + uint32_t length); 278 + 279 #endif /* __XFS_ALLOC_H__ */
+11 -13
fs/xfs/libxfs/xfs_ialloc.c
··· 2486 2487 static xfs_failaddr_t 2488 xfs_agi_verify( 2489 - struct xfs_buf *bp) 2490 { 2491 - struct xfs_mount *mp = bp->b_mount; 2492 - struct xfs_agi *agi = bp->b_addr; 2493 - int i; 2494 2495 if (xfs_has_crc(mp)) { 2496 if (!uuid_equal(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid)) ··· 2510 if (!XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum))) 2511 return __this_address; 2512 2513 if (be32_to_cpu(agi->agi_level) < 1 || 2514 be32_to_cpu(agi->agi_level) > M_IGEO(mp)->inobt_maxlevels) 2515 return __this_address; ··· 2521 if (xfs_has_finobt(mp) && 2522 (be32_to_cpu(agi->agi_free_level) < 1 || 2523 be32_to_cpu(agi->agi_free_level) > M_IGEO(mp)->inobt_maxlevels)) 2524 - return __this_address; 2525 - 2526 - /* 2527 - * during growfs operations, the perag is not fully initialised, 2528 - * so we can't use it for any useful checking. growfs ensures we can't 2529 - * use it by using uncached buffers that don't have the perag attached 2530 - * so we can detect and avoid this problem. 2531 - */ 2532 - if (bp->b_pag && be32_to_cpu(agi->agi_seqno) != bp->b_pag->pag_agno) 2533 return __this_address; 2534 2535 for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) {
··· 2486 2487 static xfs_failaddr_t 2488 xfs_agi_verify( 2489 + struct xfs_buf *bp) 2490 { 2491 + struct xfs_mount *mp = bp->b_mount; 2492 + struct xfs_agi *agi = bp->b_addr; 2493 + xfs_failaddr_t fa; 2494 + uint32_t agi_seqno = be32_to_cpu(agi->agi_seqno); 2495 + uint32_t agi_length = be32_to_cpu(agi->agi_length); 2496 + int i; 2497 2498 if (xfs_has_crc(mp)) { 2499 if (!uuid_equal(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid)) ··· 2507 if (!XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum))) 2508 return __this_address; 2509 2510 + fa = xfs_validate_ag_length(bp, agi_seqno, agi_length); 2511 + if (fa) 2512 + return fa; 2513 + 2514 if (be32_to_cpu(agi->agi_level) < 1 || 2515 be32_to_cpu(agi->agi_level) > M_IGEO(mp)->inobt_maxlevels) 2516 return __this_address; ··· 2514 if (xfs_has_finobt(mp) && 2515 (be32_to_cpu(agi->agi_free_level) < 1 || 2516 be32_to_cpu(agi->agi_free_level) > M_IGEO(mp)->inobt_maxlevels)) 2517 return __this_address; 2518 2519 for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) {