Re: Overcoming SELECT ... FOR UPDATE permission restrictions

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Alexander Lakhin <exclusion(at)gmail(dot)com>
Cc: pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: Overcoming SELECT ... FOR UPDATE permission restrictions
Date: 2018-04-13 15:55:22
Message-ID: 28360.1523634922@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Alexander Lakhin <exclusion(at)gmail(dot)com> writes:
> Can you please explain, is this a bug or intended behaviour?

I'd say it's a bug. The permissions restriction should apply even with
the intermediate view.

After some rooting around, it seems like this can be blamed on wrong
order-of-operations in ApplyRetrieveRule(). It recursively expands
sub-views, then moves the permissions bits on the RELATION RTE for the
view being expanded to the view's "OLD" RTE entry, then (if the view
is selected FOR UPDATE) applies markQueryForLocking which recursively
marks relations referenced by the view as FOR UPDATE.

markQueryForLocking knows that it should avoid touching the "OLD" and
"NEW" entries in views, because they are treated specially.
Unfortunately, that means we never mark sub-views as requiring a FOR
UPDATE permission check; since we already expanded them, their RELATION
RTEs aren't in the active jointree anymore, and we skip the OLD entry
which is now the active entry for the sub-view's permissions check.

We can fix this just by switching the order of operations so that
markQueryForLocking is applied before recursive expansion. That way,
by the time we go to expand a sub-view, its RELATION RTE has already
been marked with any needed UPDATE permission bit, and that's correctly
moved into the view's OLD entry, and you get the expected failure:

regression=> SELECT datid, datname FROM pgsd FOR UPDATE;
ERROR: permission denied for view pg_stat_database

(Note that complaining about pg_stat_database is the correct thing; the
pgsd owner's lack of UPDATE on that view is the missing permission.)

It looks to me like we could dispense with the forUpdatePushedDown
argument to ApplyRetrieveRule altogether, because with this approach
a sub-view should always have a parse rowmark already by the time we
try to expand it. I haven't tested that simplification though.

I haven't included a regression test case in this patch, but Alexander's
example can easily be converted into one.

Although this is arguably a security bug, I'm not sure we should
back-patch it. The consequences seem relatively minor, and the
behavioral change carries a significant risk of breaking applications
that worked as-intended up to now. Thoughts?

regards, tom lane

Attachment Content-Type Size
fix-propagation-of-FOR-UPDATE-into-views-1.patch text/x-diff 2.1 KB

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Tom Lane 2018-04-13 15:56:28 Re: Instability in partition_prune test?
Previous Message Julian Markwort 2018-04-13 15:48:41 Re: [PATCH] pg_hba.conf : new auth option : clientcert=verify-full