]> 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:52:40 +0000 (10:52 +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 3fc8b6a8a843be0715710b15774e2abf6553a487..b1510b0d897ae947554abb3f3011ca2c76a71ec9 100644 (file)
@@ -23,6 +23,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"
@@ -53,7 +54,9 @@ pg_control_system(PG_FUNCTION_ARGS)
        tupdesc = BlessTupleDesc(tupdesc);
 
        /* read the control file */
+       LWLockAcquire(ControlFileLock, LW_SHARED);
        ControlFile = get_controlfile(DataDir, NULL, &crc_ok);
+       LWLockRelease(ControlFileLock);
        if (!crc_ok)
                ereport(ERROR,
                                (errmsg("calculated CRC checksum does not match value stored in file")));
@@ -131,7 +134,9 @@ pg_control_checkpoint(PG_FUNCTION_ARGS)
        tupdesc = BlessTupleDesc(tupdesc);
 
        /* Read the control file. */
+       LWLockAcquire(ControlFileLock, LW_SHARED);
        ControlFile = get_controlfile(DataDir, NULL, &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, NULL, &crc_ok);
+       LWLockRelease(ControlFileLock);
        if (!crc_ok)
                ereport(ERROR,
                                (errmsg("calculated CRC checksum does not match value stored in file")));
@@ -302,7 +309,9 @@ pg_control_init(PG_FUNCTION_ARGS)
        tupdesc = BlessTupleDesc(tupdesc);
 
        /* read the control file */
+       LWLockAcquire(ControlFileLock, LW_SHARED);
        ControlFile = get_controlfile(DataDir, NULL, &crc_ok);
+       LWLockRelease(ControlFileLock);
        if (!crc_ok)
                ereport(ERROR,
                                (errmsg("calculated CRC checksum does not match value stored in file")));