Acquire ControlFileLock in relevant SQL functions.
authorThomas Munro <[email protected]>
Sun, 15 Oct 2023 21:43:47 +0000 (10:43 +1300)
committerThomas Munro <[email protected]>
Sun, 15 Oct 2023 21:47:10 +0000 (10:47 +1300)
Commit dc7d70ea added functions that read the control file, but didn't
acquire ControlFileLock.  With unlucky timing, file systems that have
weak interlocking like ext4 and ntfs could expose partially overwritten
contents, and the checksum would fail.

Back-patch to all supported releases.

Reviewed-by: David Steele <[email protected]>
Reviewed-by: Anton A. Melnikov <[email protected]>
Reviewed-by: Michael Paquier <[email protected]>
Discussion: https://postgr.es/m/20221123014224.xisi44byq3cf5psi%40awork3.anarazel.de

src/backend/utils/misc/pg_controldata.c

index 419b58330fea03e9979e5d7356a5011b2f3f027b..da61c16fc9aefdac026738886c988adfca4d08c6 100644 (file)
@@ -24,6 +24,7 @@
 #include "common/controldata_utils.h"
 #include "funcapi.h"
 #include "miscadmin.h"
+#include "storage/lwlock.h"
 #include "utils/builtins.h"
 #include "utils/pg_lsn.h"
 #include "utils/timestamp.h"
@@ -54,7 +55,9 @@ pg_control_system(PG_FUNCTION_ARGS)
    tupdesc = BlessTupleDesc(tupdesc);
 
    /* read the control file */
+   LWLockAcquire(ControlFileLock, LW_SHARED);
    ControlFile = get_controlfile(DataDir, &crc_ok);
+   LWLockRelease(ControlFileLock);
    if (!crc_ok)
        ereport(ERROR,
                (errmsg("calculated CRC checksum does not match value stored in file")));
@@ -132,7 +135,9 @@ pg_control_checkpoint(PG_FUNCTION_ARGS)
    tupdesc = BlessTupleDesc(tupdesc);
 
    /* Read the control file. */
+   LWLockAcquire(ControlFileLock, LW_SHARED);
    ControlFile = get_controlfile(DataDir, &crc_ok);
+   LWLockRelease(ControlFileLock);
    if (!crc_ok)
        ereport(ERROR,
                (errmsg("calculated CRC checksum does not match value stored in file")));
@@ -235,7 +240,9 @@ pg_control_recovery(PG_FUNCTION_ARGS)
    tupdesc = BlessTupleDesc(tupdesc);
 
    /* read the control file */
+   LWLockAcquire(ControlFileLock, LW_SHARED);
    ControlFile = get_controlfile(DataDir, &crc_ok);
+   LWLockRelease(ControlFileLock);
    if (!crc_ok)
        ereport(ERROR,
                (errmsg("calculated CRC checksum does not match value stored in file")));
@@ -300,7 +307,9 @@ pg_control_init(PG_FUNCTION_ARGS)
    tupdesc = BlessTupleDesc(tupdesc);
 
    /* read the control file */
+   LWLockAcquire(ControlFileLock, LW_SHARED);
    ControlFile = get_controlfile(DataDir, &crc_ok);
+   LWLockRelease(ControlFileLock);
    if (!crc_ok)
        ereport(ERROR,
                (errmsg("calculated CRC checksum does not match value stored in file")));