mirror of
https://github.com/postgres/postgres.git
synced 2025-08-30 06:01:21 +03:00
Fix locking in WAL receiver/sender shmem state structs
In WAL receiver and WAL server, some accesses to their corresponding shared memory control structs were done without holding any kind of lock, which could lead to inconsistent and possibly insecure results. In walsender, fix by clarifying the locking rules and following them correctly, as documented in the new comment in walsender_private.h; namely that some members can be read in walsender itself without a lock, because the only writes occur in the same process. The rest of the struct requires spinlock for accesses, as usual. In walreceiver, fix by always holding spinlock while accessing the struct. While there is potentially a problem in all branches, it is minor in stable ones. This only became a real problem in pg10 because of quorum commit in synchronous replication (commit3901fd70cc
), and a potential security problem in walreceiver because a superuser() check was removed by default monitoring roles (commit25fff40798
). Thus, no backpatch. In passing, clean up some leftover braces which were used to create unconditional blocks. Once upon a time these were used for volatile-izing accesses to those shmem structs, which is no longer required. Many other occurrences of this pattern remain. Author: Michaël Paquier Reported-by: Michaël Paquier Reviewed-by: Masahiko Sawada, Kyotaro Horiguchi, Thomas Munro, Robert Haas Discussion: https://postgr.es/m/CAB7nPqTWYqtzD=LN_oDaf9r-hAjUEPAy0B9yRkhcsLdRN8fzrw@mail.gmail.com
This commit is contained in:
@@ -711,14 +711,24 @@ SyncRepGetSyncStandbysQuorum(bool *am_sync)
|
||||
|
||||
for (i = 0; i < max_wal_senders; i++)
|
||||
{
|
||||
XLogRecPtr flush;
|
||||
WalSndState state;
|
||||
int pid;
|
||||
|
||||
walsnd = &WalSndCtl->walsnds[i];
|
||||
|
||||
SpinLockAcquire(&walsnd->mutex);
|
||||
pid = walsnd->pid;
|
||||
flush = walsnd->flush;
|
||||
state = walsnd->state;
|
||||
SpinLockRelease(&walsnd->mutex);
|
||||
|
||||
/* Must be active */
|
||||
if (walsnd->pid == 0)
|
||||
if (pid == 0)
|
||||
continue;
|
||||
|
||||
/* Must be streaming */
|
||||
if (walsnd->state != WALSNDSTATE_STREAMING)
|
||||
if (state != WALSNDSTATE_STREAMING)
|
||||
continue;
|
||||
|
||||
/* Must be synchronous */
|
||||
@@ -726,7 +736,7 @@ SyncRepGetSyncStandbysQuorum(bool *am_sync)
|
||||
continue;
|
||||
|
||||
/* Must have a valid flush position */
|
||||
if (XLogRecPtrIsInvalid(walsnd->flush))
|
||||
if (XLogRecPtrIsInvalid(flush))
|
||||
continue;
|
||||
|
||||
/*
|
||||
@@ -780,14 +790,24 @@ SyncRepGetSyncStandbysPriority(bool *am_sync)
|
||||
*/
|
||||
for (i = 0; i < max_wal_senders; i++)
|
||||
{
|
||||
XLogRecPtr flush;
|
||||
WalSndState state;
|
||||
int pid;
|
||||
|
||||
walsnd = &WalSndCtl->walsnds[i];
|
||||
|
||||
SpinLockAcquire(&walsnd->mutex);
|
||||
pid = walsnd->pid;
|
||||
flush = walsnd->flush;
|
||||
state = walsnd->state;
|
||||
SpinLockRelease(&walsnd->mutex);
|
||||
|
||||
/* Must be active */
|
||||
if (walsnd->pid == 0)
|
||||
if (pid == 0)
|
||||
continue;
|
||||
|
||||
/* Must be streaming */
|
||||
if (walsnd->state != WALSNDSTATE_STREAMING)
|
||||
if (state != WALSNDSTATE_STREAMING)
|
||||
continue;
|
||||
|
||||
/* Must be synchronous */
|
||||
@@ -796,7 +816,7 @@ SyncRepGetSyncStandbysPriority(bool *am_sync)
|
||||
continue;
|
||||
|
||||
/* Must have a valid flush position */
|
||||
if (XLogRecPtrIsInvalid(walsnd->flush))
|
||||
if (XLogRecPtrIsInvalid(flush))
|
||||
continue;
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user