Skip to content

Commit 81a448d

Browse files
author
Darrick J. Wong
committed
xfs: prevent spoofing of rtbitmap blocks when recovering buffers
While reviewing the buffer item recovery code, the thought occurred to me: in V5 filesystems we use log sequence number (LSN) tracking to avoid replaying older metadata updates against newer log items. However, we use the magic number of the ondisk buffer to find the LSN of the ondisk metadata, which means that if an attacker can control the layout of the realtime device precisely enough that the start of an rt bitmap block matches the magic and UUID of some other kind of block, they can control the purported LSN of that spoofed block and thereby break log replay. Since realtime bitmap and summary blocks don't have headers at all, we have no way to tell if a block really should be replayed. The best we can do is replay unconditionally and hope for the best. Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: Dave Chinner <[email protected]> Reviewed-by: Carlos Maiolino <[email protected]>
1 parent 9d11001 commit 81a448d

File tree

1 file changed

+12
-2
lines changed

1 file changed

+12
-2
lines changed

fs/xfs/xfs_buf_item_recover.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -698,19 +698,29 @@ xlog_recover_do_inode_buffer(
698698
static xfs_lsn_t
699699
xlog_recover_get_buf_lsn(
700700
struct xfs_mount *mp,
701-
struct xfs_buf *bp)
701+
struct xfs_buf *bp,
702+
struct xfs_buf_log_format *buf_f)
702703
{
703704
uint32_t magic32;
704705
uint16_t magic16;
705706
uint16_t magicda;
706707
void *blk = bp->b_addr;
707708
uuid_t *uuid;
708709
xfs_lsn_t lsn = -1;
710+
uint16_t blft;
709711

710712
/* v4 filesystems always recover immediately */
711713
if (!xfs_sb_version_hascrc(&mp->m_sb))
712714
goto recover_immediately;
713715

716+
/*
717+
* realtime bitmap and summary file blocks do not have magic numbers or
718+
* UUIDs, so we must recover them immediately.
719+
*/
720+
blft = xfs_blft_from_flags(buf_f);
721+
if (blft == XFS_BLFT_RTBITMAP_BUF || blft == XFS_BLFT_RTSUMMARY_BUF)
722+
goto recover_immediately;
723+
714724
magic32 = be32_to_cpu(*(__be32 *)blk);
715725
switch (magic32) {
716726
case XFS_ABTB_CRC_MAGIC:
@@ -920,7 +930,7 @@ xlog_recover_buf_commit_pass2(
920930
* the verifier will be reset to match whatever recover turns that
921931
* buffer into.
922932
*/
923-
lsn = xlog_recover_get_buf_lsn(mp, bp);
933+
lsn = xlog_recover_get_buf_lsn(mp, bp, buf_f);
924934
if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) {
925935
trace_xfs_log_recover_buf_skip(log, buf_f);
926936
xlog_recover_validate_buf_type(mp, bp, buf_f, NULLCOMMITLSN);

0 commit comments

Comments
 (0)