]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Acquire ControlFileLock in relevant SQL functions.
authorThomas Munro <tmunro@postgresql.org>
Sun, 15 Oct 2023 21:43:47 +0000 (10:43 +1300)
committerThomas Munro <tmunro@postgresql.org>
Sun, 15 Oct 2023 21:47:33 +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 <david@pgmasters.net>
Reviewed-by: Anton A. Melnikov <aamelnikov@inbox.ru>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/20221123014224.xisi44byq3cf5psi%40awork3.anarazel.de

src/backend/utils/misc/pg_controldata.c

index b42921800b732ac2ca79644e3390cf7053071135..df9526fcdd911b9d0f8f1acac830fd0ca0659547 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")));
@@ -236,7 +241,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")));
@@ -303,7 +310,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")));