On Thu, 2026-07-09 at 16:28 +0200, Andreas Lind wrote: > While working on an unrelated RLS patch, I noticed that equalPolicy() in > relcache.c doesn't compare the permissive field of RowSecurityPolicy. It > compares polcmd, hassublinks, policy_name, roles, qual, and > with_check_qual, but not permissive, so two policies that are identical > in every other respect except their PERMISSIVE/RESTRICTIVE designation > are reported as equal. > > equalPolicy() is used (via equalRSDesc()) by RelationRebuildRelation() > to decide whether an open relation's existing row-security descriptor > can be kept as-is across a relcache rebuild, or must be treated as > changed. ALTER POLICY has no way to flip a policy's > PERMISSIVE/RESTRICTIVE designation, but DROP POLICY followed by CREATE > POLICY of the same name, roles, command, and quals, differing only in AS > PERMISSIVE/RESTRICTIVE, hits this exactly: the stale descriptor would be > kept, leaving the relcache out of sync with how the policy should now > combine with others (PERMISSIVE policies are ORed together; RESTRICTIVE > policies are ANDed with the rest). > > I wasn't able to construct a simple SQL reproduction: > RelationRebuildRelation() (and thus this comparison) is only reached > while the relation is still open (refcount > 0) at the moment its > invalidation is processed. Closing and reopening the relation between > statements -- the usual behavior -- sidesteps the bug, and a second > session can't hold the relation open across the DROP/CREATE either, > since both need AccessExclusiveLock. This looks analogous to > ab6d1cd26eb, which fixed the same kind of omission in this function for > the USING qual and likewise shipped without a test.
I don't know if the omission to check for identical PERMISSIVE or RESTRICTIVE settings can lead to real problems, but I feel that it violates the promise of the function. So I am +1 on this change. Yours, Laurenz Albe
