On Mon, Apr 29, 2024 at 09:01:58AM +0200, Christoph Hellwig wrote: > Commit a70f9fe52daa ("xfs: detect and handle invalid iclog size set by > mkfs") added a fixup for incorrect h_size values used for the initial > umount record in old xfsprogs versions. But it is not using this fixed > up value to size the log recovery buffer, which can lead to an out of > bounds access when the incorrect h_size does not come from the old mkfs > tool, but a fuzzer. > > Fix this by open coding xlog_logrec_hblks and taking the fixed h_size > into account for this calculation. > > Fixes: a70f9fe52daa ("xfs: detect and handle invalid iclog size set by mkfs") Modulo what bfoster said about the tagging, Reviewed-by: Darrick J. Wong <djwong@xxxxxxxxxx> --D > Reported-by: Sam Sun <samsun1006219@xxxxxxxxx> > Signed-off-by: Christoph Hellwig <hch@xxxxxx> > --- > fs/xfs/xfs_log_recover.c | 20 ++++++++++++++------ > 1 file changed, 14 insertions(+), 6 deletions(-) > > diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c > index b445e8ce4a7d21..bb8957927c3c2e 100644 > --- a/fs/xfs/xfs_log_recover.c > +++ b/fs/xfs/xfs_log_recover.c > @@ -2999,7 +2999,7 @@ xlog_do_recovery_pass( > int error = 0, h_size, h_len; > int error2 = 0; > int bblks, split_bblks; > - int hblks, split_hblks, wrapped_hblks; > + int hblks = 1, split_hblks, wrapped_hblks; > int i; > struct hlist_head rhash[XLOG_RHASH_SIZE]; > LIST_HEAD (buffer_list); > @@ -3055,14 +3055,22 @@ xlog_do_recovery_pass( > if (error) > goto bread_err1; > > - hblks = xlog_logrec_hblks(log, rhead); > - if (hblks != 1) { > - kvfree(hbp); > - hbp = xlog_alloc_buffer(log, hblks); > + /* > + * This open codes xlog_logrec_hblks so that we can reuse the > + * fixed up h_size value calculated above. Without that we'd > + * still allocate the buffer based on the incorrect on-disk > + * size. > + */ > + if (h_size > XLOG_HEADER_CYCLE_SIZE && > + (rhead->h_version & cpu_to_be32(XLOG_VERSION_2))) { > + hblks = DIV_ROUND_UP(h_size, XLOG_HEADER_CYCLE_SIZE); > + if (hblks > 1) { > + kvfree(hbp); > + hbp = xlog_alloc_buffer(log, hblks); > + } > } > } else { > ASSERT(log->l_sectBBsize == 1); > - hblks = 1; > hbp = xlog_alloc_buffer(log, 1); > h_size = XLOG_BIG_RECORD_BSIZE; > } > -- > 2.39.2 > >