8000 Fix mislabeling of PROC_QUEUE->links as PGPROC, fixing UBSan on 32bit · postgres/postgres@140c803 · GitHub
[go: up one dir, main page]

Skip to content

Commit 140c803

Browse files
committed
Fix mislabeling of PROC_QUEUE->links as PGPROC, fixing UBSan on 32bit
ProcSleep() used a PGPROC* variable to point to PROC_QUEUE->links.next, because that does "the right thing" with SHMQueueInsertBefore(). While that largely works, it's certainly not correct and unnecessary - we can just use SHM_QUEUE* to point to the insertion point. Noticed when testing a 32bit of postgres with undefined behavior sanitizer. UBSan noticed that sometimes the supposed PGPROC wasn't sufficiently aligned (required since 46d6e5f, ensured indirectly, via ShmemAllocRaw() guaranteeing cacheline alignment). For now fix this by using a SHM_QUEUE* for the insertion point. Subsequently we should replace all the use of PROC_QUEUE and SHM_QUEUE with ilist.h, but that's a larger change that we don't want to backpatch. Backpatch to all supported versions - it's useful to be able to run postgres under UBSan. Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Discussion: https://postgr.es/m/20221117014230.op5kmgypdv2dtqsf@awork3.anarazel.de Backpatch: 11-
1 parent 8687cee commit 140c803

File tree

1 file changed

+14
-10
lines changed
  • src/backend/storage/lmgr

1 file changed

+14
-10
lines changed

src/backend/storage/lmgr/proc.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,11 +1051,11 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
10511051
uint32 hashcode = locallock->hashcode;
10521052
LWLock *partitionLock = LockHashPartitionLock(hashcode);
10531053
PROC_QUEUE *waitQueue = &(lock->waitProcs);
1054+
SHM_QUEUE *waitQueuePos;
10541055
LOCKMASK myHeldLocks = MyProc->heldLocks;
10551056
bool early_deadlock = false;
10561057
bool allow_autovacuum_cancel = true;
10571058
int myWaitStatus;
1058-
PGPROC *proc;
10591059
PGPROC *leader = MyProc->lockGroupLeader;
10601060
int i;
10611061

@@ -1097,21 +1097,24 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
10971097
* we are only considering the part of the wait queue before my insertion
10981098
* point.
10991099
*/
1100-
if (myHeldLocks != 0)
1100+
if (myHeldLocks != 0 && waitQueue->size > 0)
11011101
{
11021102
LOCKMASK aheadRequests = 0;
1103+
SHM_QUEUE *proc_node;
11031104

1104-
proc = (PGPROC *) waitQueue->links.next;
1105+
proc_node = waitQueue->links.next;
11051106
for (i = 0; i < waitQueue->size; i++)
11061107
{
1108+
PGPROC *proc = (PGPROC *) proc_node;
1109+
11071110
/*
11081111
* If we're part of the same locking group as this waiter, its
11091112
* locks neither conflict with ours nor contribute to
11101113
* aheadRequests.
11111114
*/
11121115
if (leader != NULL && leader == proc->lockGroupLeader)
11131116
{
1114-
proc = (PGPROC *) proc->links.next;
1117+
proc_node = proc->links.next;
11151118
continue;
11161119
}
11171120
/* Must he wait for me? */
@@ -1148,24 +1151,25 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
11481151
}
11491152
/* Nope, so advance to next waiter */
11501153
aheadRequests |= LOCKBIT_ON(proc->waitLockMode);
1151-
proc = (PGPROC *) proc->links.next;
1154+
proc_node = proc->links.next;
11521155
}
11531156

11541157
/*
1155-
* If we fall out of loop normally, proc points to waitQueue head, so
1156-
* we will insert at tail of queue as desired.
1158+
* If we iterated through the whole queue, cur points to the waitQueue
1159+
* head, so we will insert at tail of queue as desired.
11571160
*/
1161+
waitQueuePos = proc_node;
11581162
}
11591163
else
11601164
{
11611165
/* I hold no locks, so I can't push in front of anyone. */
1162-
proc = (PGPROC *) &(waitQueue->links);
1166+
waitQueuePos = &waitQueue->links;
11631167
}
11641168

11651169
/*
1166-
* Insert self into queue, ahead of the given proc (or at tail of queue).
1170+
* Insert self into queue, at the position determined above.
11671171
*/
1168-
SHMQueueInsertBefore(&(proc->links), &(MyProc->links));
1172+
SHMQueueInsertBefore(waitQueuePos, &MyProc->links);
11691173
waitQueue->size++;
11701174

11711175
lock->waitMask |= LOCKBIT_ON(lockmode);

0 commit comments

Comments
 (0)
0