Message ID | 20240906211136.70391-4-catherine.hoang@oracle.com (mailing list archive) |
---|---|
State | Not Applicable, archived |
Headers | show |
Series | xfs backports for 6.6.y (from 6.10) | expand |
On Fri, Sep 06, 2024 at 02:11:17 PM -0700, Catherine Hoang wrote: > From: Christoph Hellwig <hch@lst.de> > > commit 45cf976008ddef4a9c9a30310c9b4fb2a9a6602a upstream. > > [backport: resolve conflict due to kmem_free->kvfree conversion] > > 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. Later commit 0c771b99d6c9 > ("xfs: clean up calculation of LR header blocks") cleaned up the log > reover buffer calculation, but stoped using the fixed up h_size 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. Looks like this commit has already been backported to 6.6.y. Please refer to https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=c2389c074973aa94e34992e7f66dac0de37595b5
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 57f366c3d355..9f9d3abad2cf 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -2965,7 +2965,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); @@ -3021,14 +3021,22 @@ xlog_do_recovery_pass( if (error) goto bread_err1; - hblks = xlog_logrec_hblks(log, rhead); - if (hblks != 1) { - kmem_free(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) { + kmem_free(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; }