Skip to content

Commit 45cf976

Browse files
Christoph HellwigChandan Babu R
authored andcommitted
xfs: fix log recovery buffer allocation for the legacy h_size fixup
Commit a70f9fe ("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 0c771b9 ("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. Fixes: 0c771b9 ("xfs: clean up calculation of LR header blocks") Reported-by: Sam Sun <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]> Reviewed-by: Brian Foster <[email protected]> Reviewed-by: "Darrick J. Wong" <[email protected]> Signed-off-by: Chandan Babu R <[email protected]>
1 parent 0370f9b commit 45cf976

File tree

1 file changed

+14
-6
lines changed

1 file changed

+14
-6
lines changed

fs/xfs/xfs_log_recover.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2999,7 +2999,7 @@ xlog_do_recovery_pass(
29992999
int error = 0, h_size, h_len;
30003000
int error2 = 0;
30013001
int bblks, split_bblks;
3002-
int hblks, split_hblks, wrapped_hblks;
3002+
int hblks = 1, split_hblks, wrapped_hblks;
30033003
int i;
30043004
struct hlist_head rhash[XLOG_RHASH_SIZE];
30053005
LIST_HEAD (buffer_list);
@@ -3055,14 +3055,22 @@ xlog_do_recovery_pass(
30553055
if (error)
30563056
goto bread_err1;
30573057

3058-
hblks = xlog_logrec_hblks(log, rhead);
3059-
if (hblks != 1) {
3060-
kvfree(hbp);
3061-
hbp = xlog_alloc_buffer(log, hblks);
3058+
/*
3059+
* This open codes xlog_logrec_hblks so that we can reuse the
3060+
* fixed up h_size value calculated above. Without that we'd
3061+
* still allocate the buffer based on the incorrect on-disk
3062+
* size.
3063+
*/
3064+
if (h_size > XLOG_HEADER_CYCLE_SIZE &&
3065+
(rhead->h_version & cpu_to_be32(XLOG_VERSION_2))) {
3066+
hblks = DIV_ROUND_UP(h_size, XLOG_HEADER_CYCLE_SIZE);
3067+
if (hblks > 1) {
3068+
kvfree(hbp);
3069+
hbp = xlog_alloc_buffer(log, hblks);
3070+
}
30623071
}
30633072
} else {
30643073
ASSERT(log->l_sectBBsize == 1);
3065-
hblks = 1;
30663074
hbp = xlog_alloc_buffer(log, 1);
30673075
h_size = XLOG_BIG_RECORD_BSIZE;
30683076
}

0 commit comments

Comments
 (0)