[Bug] Usage of stale dead_items pointer in parallel vacuum - Mailing list pgsql-bugs

From Kevin Oommen Anish
Subject [Bug] Usage of stale dead_items pointer in parallel vacuum
Date
Msg-id 199a07cbdfc.7a1c4aac25838.1675074408277594551@zohocorp.com
Whole thread Raw
Responses Re: [Bug] Usage of stale dead_items pointer in parallel vacuum
Re: [Bug] Usage of stale dead_items pointer in parallel vacuum
List pgsql-bugs
Hello Developers,    
We have discovered a bug in the dead_items_reset function in PG v17 specifically near the parallel_vacuum_reset_dead_items function() invocation. The bug is still prevalent in the latest version v18 as well. Although it was introduced in v17, it was detected while running the vacuum.sql regression tests which were introduced in PG v17.5.

In dead_items_reset function, we destroy and recreate the shared TidStore by invoking the parallel_vacuum_reset_dead_items() function. However, after the reallocation, the vacrel->dead_items pointer is not updated to point to the newly allocated TidStore. As a result, the leader process continues to hold a pointer to the destroyed TidStore. As a result, subsequent calls by the leader process to dead_items_add() go through this stale pointer, resulting in a use-after-free.

However this goes unnoticed since the freeing and reallocation of the shared TidStore (vacrel->pvs->dead_items) are so close to each other, that the AllocSet memory context always hands back the exact same chunk of memory that was freed previously, making the stale vacrel->dead_items pointer still appear valid even though it technically points to freed storage.
This issue was reproduced while running the existing regression tests from vacuum.sql with our custom malloc allocator implementation. For your reference, we have previously shared our custom malloc allocator implementation in a separate bug fix. (message ID: 1936493cc38.68cb2ef27266.7456585136086197135@zohocorp.com).The corresponding crash backtrace is attached as well.

Failed regression:
CREATE TABLE pvactst2 (i INT) WITH (autovacuum_enabled = off);
INSERT INTO pvactst2 SELECT generate_series(1, 1000);
CREATE INDEX ON pvactst2 (i);
CREATE INDEX ON pvactst2 (i);
SET min_parallel_index_scan_size to 0;
SET maintenance_work_mem TO 64;
INSERT INTO pvactst2 SELECT generate_series(1, 1000);
DELETE FROM pvactst2 WHERE i < 1000;
VACUUM (PARALLEL 2) pvactst2;

Please let me know if you have any questions or would like further details.
Thanks & Regards,
Kevin Oommen Anish
Member Technical Staff
ZOHO Corporation


Attachment

pgsql-bugs by date:

Previous
From: "White, Ian Keith"
Date:
Subject: IN List operator , where list of values are over a number of lines
Next
From: Pavel Stehule
Date:
Subject: Re: IN List operator , where list of values are over a number of lines