Re: Avoid orphaned objects dependencies, take 3
Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
From: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
To: Heikki Linnakangas <hlinnaka@iki.fi>
Cc: Robert Haas <robertmhaas@gmail.com>, Jeff Davis <pgsql@j-davis.com>, Roman Eskin <r.eskin@arenadata.io>, Michael Paquier <michael@paquier.xyz>, Alexander Lakhin <exclusion@gmail.com>, pgsql-hackers@lists.postgresql.org, Tom Lane <tgl@sss.pgh.pa.us>
Date: 2026-06-01T09:21:39Z
Lists: pgsql-hackers
Attachments
Hi, On Wed, May 27, 2026 at 06:53:35PM +0300, Heikki Linnakangas wrote: > Fixed these, and did some more copy-editing on the comments. With that, > committed and backpatched. Thanks! Now that we avoid orphaned objects dependencies, I resumed working on Robert's concern about the TOCTOU window where a REVOKE could land between the original permission check and the dependency recording. Based on our discussion during PGConf.dev, PFA a new patch that uses the same approach as RangeVarGetRelidExtended(): record SharedInvalidMessageCounter at the time of the original aclcheck, then before locking compare the current counter to the saved value. If it changed, recheck permission before acquiring the lock. After the lock wait, if more invalidations arrived, release and retry. Remarks: The tracking array lives in a dedicated AclCheckTrackContext memory context (child of TopMemoryContext). The context is reset at the start of each top-level utility statement, which frees all prior allocations and provides clean lifetime management. Recording is gated by aclcheck_tracking_active, which is set to true only during top-level utility statement execution. This ensures DML and queries pay no cost. The flag is cleared both at normal completion of ProcessUtility and in AbortTransaction to handle the error path. The patch adds a test that would fail without the TOCTOU protection in place. Alternatives considered: - To avoid allocating memory for each statement, keep the array in TopMemoryContext and never free it (only resetting the count). But that left the high-water mark allocated for the lifetime of the backend. - Passing privilege info (roleId, mode) as extra arguments through the dependency recording APIs (recordDependencyOn, recordMultipleDependencies, etc.). It was discarded because expression-based dependencies (recordDependencyOnExpr, find_expr_references_walker) discover objects by walking expression trees: the caller never sees individual objects and cannot attach privilege info to them. That's why I believe the tracking approach that is in the attached sounds like a right approach. Bonus point, it would also help if we want to "ensure" that we always do the acl check prior the dependency recording: that would avoid cases like the one mentioned in [1] (for example, when we can create a view and then record a dependency based on a function we don't have exec privilege on). [1]: https://postgr.es/m/agsCqlLTytZCudMv%40bdtpg Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Avoid orphaned objects dependencies
- 2fbb21170e90 19 (unreleased) landed
- 5100bdbd3ba2 14 (unreleased) landed
- 5fa137727db0 15 (unreleased) landed
- d9bc0d96c247 16 (unreleased) landed
- 3a9909eda207 17 (unreleased) landed
- c8cd3d6976f7 18 (unreleased) landed
-
Don't try to record dependency on a dropped column's datatype
- fd93ee100830 19 (unreleased) landed
- 36b6ed2606e1 14 (unreleased) landed
- ef3d7b15e4cd 15 (unreleased) landed
- d44cd467471c 16 (unreleased) landed
- c1588f92a915 17 (unreleased) landed
- f9d5a52da4ca 18 (unreleased) landed