From: | Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp> |
---|---|
To: | Florian Pflug <fgp(at)phlo(dot)org> |
Cc: | Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Robert Haas <robertmhaas(at)gmail(dot)com>, PgHacker <pgsql-hackers(at)postgresql(dot)org> |
Subject: | Re: [RFC] Interface of Row Level Security |
Date: | 2012-06-05 13:07:42 |
Message-ID: | CADyhKSUe1bHRQyY3aE+jQMqyEWfOJALR3hzRh_h8HEEAAihMfA@mail.gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
2012/6/5 Florian Pflug <fgp(at)phlo(dot)org>:
> On Jun5, 2012, at 11:43 , Kohei KaiGai wrote:
>> 2012/6/5 Florian Pflug <fgp(at)phlo(dot)org>:
>>> What's to be gained by that? Once there's *any* way to bypass a RLS
>>> policy, you'll have to deal with the plan invalidation issues you
>>> mentioned anyway. ISTM that complexity-wide, you don't save much by not
>>> having RLSBYPASS (or something similar), but feature-wise you lose at
>>> lot…
>
>> All we need to change is selection of the function to be appended
>> automatically. In case when superusers are allowed to bypass RLS
>> policy, "OR has_superuser_privilege()" shall be appended to the
>> user given clause, however, "OR has_table_privilege()" shall be
>> appended instead in case of RLSBYPASS permission.
>> (Note that has_table_privilege() always true for superusers.)
>>
>> I think it does not require to add a mechanism to invalidate
>> prepared-statement, because all the checks are applied on
>> executor stage. And these functions can be stable functions,
>> so I believe some enhancements at planner will correctly wipe
>> out prior to query execution at the next step.
>
> That won't work, since the current role can change any time mid-query,
> at least if you're using cursors. Here's an example
>
> First, setup a table
>> CREATE TABLE data AS SELECT id FROM generate_series(1,1000000) AS id;
>> GRANT SELECT ON data TO PUBLIC;
>
> Then create a cursor which doesn't materialize its result
>> BEGIN;
>> DECLARE mycursor NO SCROLL CURSOR WITHOUT HOLD FOR
> SELECT id, current_user FROM data;
>> SET ROLE=anybody;
>> FETCH mycursor;
> id | current_user
> ----+--------------
> 1 | anybody
> (1 row)
>> SET role=somebody;
>> FETCH mycursor;
> id | current_user
> ----+--------------
> 2 | somebody
> (1 row)
>> ROLLBACK;
>
> And now, for comparison, a cursor which does materialize its result
>> BEGIN;
>> DECLARE mycursor NO SCROLL CURSOR WITHOUT HOLD FOR
> SELECT id, current_user FROM data ORDER BY id;
>> SET ROLE=anybody;
>> FETCH mycursor;
> id | current_user
> ----+--------------
> 1 | anybody
> (1 row)
>
>> SET role=somebody;
>> FETCH mycursor;
> id | current_user
> ----+--------------
> 2 | anybody
> (1 row)
>
> Imagine that the current_user function call was actually part of the
> RLS policy. Then the example above shows that *which* role we check
> access against (the one active at the first fetch, or currently active
> one) depends on which plan the optimizer happens to pick. This, IMHO,
> is not acceptable for a security feature like RLS.
>
Which is your expected behavior in this example?
In case when the query is internally materialized, the current_user function
is *already* executed prior to switch user-id, thus, the result set internally
stored in was already filtered out using older user-id.
It seems to me, caution of the problem is current_user is performing out
of the snapshot controls. According to the definition of stable function,
its result should not be changed during a particular scan.
At least, it is not a fundamental problem of RLS implementation, although
it needs to take an enhancement something like effective user-id per
snapshot basis.
Thanks,
--
KaiGai Kohei <kaigai(at)kaigai(dot)gr(dot)jp>
From | Date | Subject | |
---|---|---|---|
Next Message | Tom Lane | 2012-06-05 13:17:39 | Re: No, pg_size_pretty(numeric) was not such a hot idea |
Previous Message | Magnus Hagander | 2012-06-05 12:53:44 | pg_receivexlog and feedback message |