From 7e7c5ab2063c7edc444fa31a031f26618a8179a9 Mon Sep 17 00:00:00 2001 From: XDTG Date: Fri, 28 Jun 2024 14:21:37 +0800 Subject: [PATCH] zfs: add bounds checking to zil_parse Make sure log record don't stray beyond valid memory region. There is a lack of verification of the space occupied by fixed members of lr_t in the zil_parse. We can create a crafted image to trigger an out of bounds read by following these steps: 1) Do some file operations and reboot to simulate abnormal exit without umount 2) zil_chain.zc_nused: 0x1000 3) First lr_t lr_t.lrc_txtype: 0x0 lr_t.lrc_reclen: 0x1000-0xb8-0x1 lr_t.lrc_txg: 0x0 lr_t.lrc_seq: 0x1 4) Update checksum in zil_chain.zc_eck Fix: Add some checks to make sure the remaining bytes are large enough to hold an log record. Signed-off-by: XDTG --- module/zfs/zil.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/module/zfs/zil.c b/module/zfs/zil.c index 34be54b337fd..fcd9ee2fe31e 100644 --- a/module/zfs/zil.c +++ b/module/zfs/zil.c @@ -512,9 +512,23 @@ zil_parse(zilog_t *zilog, zil_parse_blk_func_t *parse_blk_func, for (; lrp < end; lrp += reclen) { lr_t *lr = (lr_t *)lrp; + + /* + * Are the remaining bytes large enough to hold an + * log record? + */ + if ((char *)(lr + 1) > end) { + error = SET_ERROR(EUCLEAN); + arc_buf_destroy(abuf, &abuf); + goto done; + } reclen = lr->lrc_reclen; - ASSERT3U(reclen, >=, sizeof (lr_t)); - ASSERT3U(reclen, <=, end - lrp); + if (reclen < sizeof(lr_t) || reclen > end - lrp) { + error = SET_ERROR(EUCLEAN); + arc_buf_destroy(abuf, &abuf); + goto done; + } + if (lr->lrc_seq > claim_lr_seq) { arc_buf_destroy(abuf, &abuf); goto done;