From: | Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp> |
---|---|
To: | Robert Haas <robertmhaas(at)gmail(dot)com> |
Cc: | Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Noah Misch <noah(at)leadboat(dot)com>, Kevin Grittner <Kevin(dot)Grittner(at)wicourts(dot)gov>, Kohei(dot)Kaigai(at)emea(dot)nec(dot)com, thom(at)linux(dot)com, pgsql-hackers(at)postgresql(dot)org |
Subject: | Re: [v9.2] Fix Leaky View Problem |
Date: | 2011-11-02 11:34:42 |
Message-ID: | CADyhKSV2t18hCX2oq14ob565OgkwpLD-z7GFi1qv-fGsqLkVwg@mail.gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
The attached patches are fixes to the leaky-view problem; a
prerequisite to implement
row-level security; that consists of two portion.
Part-1)
It adds WITH(options...) clause on view definition, and disallow to
make sub-queries
flatten, if this sub-query is originated a particular view with
"security_barrier" reloption.
In addition, it also disallow to push-down qualifiers across
security-barrier, thus, we
will have a way to guarantee order to launch qualifiers; that has been
headache for us
to achieve row-level security using view (or possibly similar feature).
Part-2)
It adds "leakproof" attribute to functions; that means functions are
obviously leakproof
to the supplied arguments, and only superuser can set.
If a qualifier is consists of functions with "leakproof" only, the
query planner handles it
as an exception of the security-barrier. A typical case is WHERE x =
100; that shall
promote the given scan plan from sequential to index in many cases.
It requires the part-1 being applied prior to this patch, and
compressed by gzip due to
the size of patch (mostly pg_proc.h).
The following examples shows how these features works:
postgres=# CREATE VIEW v1 AS SELECT * FROM t1 WHERE a % 2 =0;
CREATE VIEW
postgres=# CREATE VIEW v1s WITH (security_barrier) AS SELECT * FROM t1
WHERE a % 2 =0;
CREATE VIEW
postgres=# CREATE VIEW v2 AS SELECT * FROM t1 JOIN t2 ON a = x WHERE a % 2 = 0;
CREATE VIEW
postgres=# CREATE VIEW v2s WITH (security_barrier) AS SELECT * FROM t1
JOIN t2 ON a = x W
HERE a % 2 = 0;
CREATE VIEW
postgres=# CREATE OR REPLACE FUNCTION f_leak(text) RETURNS bool
LANGUAGE plpgsql COST 0.0001
AS 'BEGIN RAISE notice ''f_leak => %'', $1; RETURN true;
END';CREATE FUNCTION
Without security_barrier
------------------------------------
postgres=# SELECT * FROM v1 WHERE f_leak(b);NOTICE: f_leak =>
aaaNOTICE: f_leak => bbbNOTICE: f_leak => cccNOTICE: f_leak => ddd
a | b---+----- 2 | bbb 4 | ddd(2 rows)
postgres=# EXPLAIN SELECT * FROM v1 WHERE f_leak(b);
QUERY PLAN
----------------------------------------------------
Seq Scan on t1 (cost=0.00..28.45 rows=2 width=36)
Filter: (f_leak(b) AND ((a % 2) = 0))
(2 rows)
postgres=# SELECT * FROM v2 WHERE f_leak(y);
NOTICE: f_leak => xxx
NOTICE: f_leak => yyy
NOTICE: f_leak => zzz
NOTICE: f_leak => xyz
a | b | x | y
---+-----+---+-----
2 | bbb | 2 | xxx
4 | ddd | 4 | zzz
(2 rows)
postgres=# EXPLAIN SELECT * FROM v2 WHERE f_leak(y);
QUERY PLAN
----------------------------------------------------------------
Hash Join (cost=28.52..52.38 rows=2 width=72)
Hash Cond: (t2.x = t1.a)
-> Seq Scan on t2 (cost=0.00..22.30 rows=410 width=36)
Filter: f_leak(y)
-> Hash (cost=28.45..28.45 rows=6 width=36)
-> Seq Scan on t1 (cost=0.00..28.45 rows=6 width=36)
Filter: ((a % 2) = 0)
(7 rows)
With security_barrier
-------------------------------
postgres=# SELECT * FROM v1s WHERE f_leak(b);NOTICE: f_leak =>
bbbNOTICE: f_leak => ddd a | b---+----- 2 | bbb 4 | ddd(2 rows)
postgres=# EXPLAIN SELECT * FROM v1s WHERE f_leak(b);
QUERY PLAN
----------------------------------------------------------
Subquery Scan on v1s (cost=0.00..28.51 rows=2 width=36)
Filter: f_leak(v1s.b)
-> Seq Scan on t1 (cost=0.00..28.45 rows=6 width=36)
Filter: ((a % 2) = 0)
(4 rows)
postgres=# SELECT * FROM v2s WHERE f_leak(y);
NOTICE: f_leak => xxx
NOTICE: f_leak => zzz
a | b | x | y
---+-----+---+-----
2 | bbb | 2 | xxx
4 | ddd | 4 | zzz
(2 rows)
postgres=# EXPLAIN SELECT * FROM v2s WHERE f_leak(y);
QUERY PLAN
----------------------------------------------------------------------
Subquery Scan on v2s (cost=28.52..55.56 rows=2 width=72)
Filter: f_leak(v2s.y)
-> Hash Join (cost=28.52..55.50 rows=6 width=72)
Hash Cond: (t2.x = t1.a)
-> Seq Scan on t2 (cost=0.00..22.30 rows=1230 width=36)
-> Hash (cost=28.45..28.45 rows=6 width=36)
-> Seq Scan on t1 (cost=0.00..28.45 rows=6 width=36)
Filter: ((a % 2) = 0)
(8 rows)
Leakproof function is exceptionally allowed to be pushed down
------------------------------------------------------------------------------------------
postgres=# SELECT * FROM v2s WHERE f_leak(y) AND a = 2;
NOTICE: f_leak => xxx
a | b | x | y
---+-----+---+-----
2 | bbb | 2 | xxx
(1 row)
(*) int4eq is set as a leakproof function in the default.
postgres=# EXPLAIN SELECT * FROM v2s WHERE f_leak(y) AND a = 2;
QUERY PLAN
-------------------------------------------------------------------------------
Subquery Scan on v2s (cost=0.00..16.56 rows=1 width=72)
Filter: f_leak(v2s.y)
-> Nested Loop (cost=0.00..16.55 rows=1 width=72)
-> Index Scan using t1_pkey on t1 (cost=0.00..8.27 rows=1 width=36)
Index Cond: (a = 2)
Filter: ((a % 2) = 0)
-> Index Scan using t2_pkey on t2 (cost=0.00..8.27 rows=1 width=36)
Index Cond: (x = 2)
(8 rows)
Thanks,
2011/10/21 Robert Haas <robertmhaas(at)gmail(dot)com>:
> On Fri, Oct 21, 2011 at 10:36 AM, Kohei KaiGai <kaigai(at)kaigai(dot)gr(dot)jp> wrote:
>> So, I will split the patch into two parts as follows, in the next commit fest.
>>
>> Part-1) Views with security_barrier reloption
>>
>> The part-1 portion provides views "security_barrier" reloption; that enables
>> to keep sub-queries unflatten in the prepjoin.c stage.
>> In addition, these sub-queries (that originally come from views with
>> "security_barrier" option) don't allow to push down qualifiers from upper
>> level. It shall prevent both of the problematic scenarios.
>>
>> Part-2) Functions with leakproof attribute
>>
>> The part-2 portion provides functions "leakproof" attribute; that enables
>> to push down leakproof functions into sub-queries, even if it originally
>> come from security views.
>> It shall minimize performance damages when we use view for row-level
>> security purpose.
>
> Sounds reasonable.
>
> --
> Robert Haas
> EnterpriseDB: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
--
KaiGai Kohei <kaigai(at)kaigai(dot)gr(dot)jp>
Attachment | Content-Type | Size |
---|---|---|
pgsql-v9.2-fix-leaky-view.part-1.v5.patch | application/octet-stream | 41.9 KB |
pgsql-v9.2-fix-leaky-view.part-2.v5.patch.gz | application/x-gzip | 72.6 KB |
From | Date | Subject | |
---|---|---|---|
Next Message | Simon Riggs | 2011-11-02 11:56:46 | Re: Hot Backup with rsync fails at pg_clog if under load |
Previous Message | Kohei KaiGai | 2011-11-02 10:41:19 | Add permission checks on SELECT INTO |