postgres.git / summary / log / commit / refs

commit    48eb6a3c895dac239f7e04fc3d62c09a17c1fc4a
Author:   Thomas Munro <tmunro@postgresql.org>
Date:     Mon Jun 08 01:57:24 2020 +0000
First released in: 14.0, 9.5.23, 9.6.19, 10.14, 11.9, 12.4, 13.0

    Fix locking bugs that could corrupt pg_control.
    
    The redo routines for XLOG_CHECKPOINT_{ONLINE,SHUTDOWN} must acquire
    ControlFileLock before modifying ControlFile->checkPointCopy, or the
    checkpointer could write out a control file with a bad checksum.
    
    Likewise, XLogReportParameters() must acquire ControlFileLock before
    modifying ControlFile and calling UpdateControlFile().
    
    Back-patch to all supported releases.
    
    Author: Nathan Bossart <bossartn@amazon.com>
    Author: Fujii Masao <masao.fujii@oss.nttdata.com>
    Reviewed-by: Fujii Masao <masao.fujii@oss.nttdata.com>
    Reviewed-by: Michael Paquier <michael@paquier.xyz>
    Reviewed-by: Thomas Munro <thomas.munro@gmail.com>
    Discussion: https://postgr.es/m/70BF24D6-DC51-443F-B55A-95735803842A%40amazon.com


src/backend/access/transam/xlog.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 28f19f1c786..bceef897d6e 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -9680,6 +9680,8 @@ XLogReportParameters(void) XLogFlush(recptr); } + LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); + ControlFile->MaxConnections = MaxConnections; ControlFile->max_worker_processes = max_worker_processes; ControlFile->max_prepared_xacts = max_prepared_xacts; @@ -9688,6 +9690,8 @@ XLogReportParameters(void) ControlFile->wal_log_hints = wal_log_hints; ControlFile->track_commit_timestamp = track_commit_timestamp; UpdateControlFile(); + + LWLockRelease(ControlFileLock); } } @@ -9912,8 +9916,10 @@ xlog_redo(XLogReaderState *record) } /* ControlFile->checkPointCopy always tracks the latest ckpt XID */ + LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); ControlFile->checkPointCopy.nextXidEpoch = checkPoint.nextXidEpoch; ControlFile->checkPointCopy.nextXid = checkPoint.nextXid; + LWLockRelease(ControlFileLock); /* Update shared-memory copy of checkpoint XID/epoch */ SpinLockAcquire(&XLogCtl->info_lck); @@ -9971,8 +9977,10 @@ xlog_redo(XLogReaderState *record) SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB); /* ControlFile->checkPointCopy always tracks the latest ckpt XID */ + LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); ControlFile->checkPointCopy.nextXidEpoch = checkPoint.nextXidEpoch; ControlFile->checkPointCopy.nextXid = checkPoint.nextXid; + LWLockRelease(ControlFileLock); /* Update shared-memory copy of checkpoint XID/epoch */ SpinLockAcquire(&XLogCtl->info_lck); [parent: a35896c4b2a1]