mirror of
				https://git.proxmox.com/git/mirror_zfs.git
				synced 2025-10-26 18:05:04 +03:00 
			
		
		
		
	zfs: add bounds checking to zil_parse (#16308)
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 <click1799@163.com>
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
			
			
This commit is contained in:
		
							parent
							
								
									d4b5517ef9
								
							
						
					
					
						commit
						ec580bc520
					
				@ -527,9 +527,26 @@ 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) {
 | 
			
		||||
				cmn_err(CE_WARN, "zil_parse: lr_t overrun");
 | 
			
		||||
				error = SET_ERROR(ECKSUM);
 | 
			
		||||
				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) {
 | 
			
		||||
				cmn_err(CE_WARN,
 | 
			
		||||
				    "zil_parse: lr_t has an invalid reclen");
 | 
			
		||||
				error = SET_ERROR(ECKSUM);
 | 
			
		||||
				arc_buf_destroy(abuf, &abuf);
 | 
			
		||||
				goto done;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (lr->lrc_seq > claim_lr_seq) {
 | 
			
		||||
				arc_buf_destroy(abuf, &abuf);
 | 
			
		||||
				goto done;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user